Repository navigation
feat(wasm-sdk): seal and scan DashPay private contact requests #5811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
QuantumExplorer
merged 75 commits into
v5.1-dev
from
feat/wasm-sdk-private-contact-requests
Nov 9, 2026
Merged
Changes from 53 commits
Commits
Show all changes
75 commits
Select commit
Hold shift + click to select a range
5fa4714
test(sdk): open an entry with the first of a wallet's prepared keys
QuantumExplorer 1549627
feat(sdk): send, scan and read private contact requests
QuantumExplorer ef1a5ce
feat(wasm-sdk): read private document pages and seal and scan private…
QuantumExplorer a6ca844
feat(sdk): name the sender key of a recovered private contact request
QuantumExplorer c3f1b0d
feat(sdk): sign private contact requests with the sender's signing key
QuantumExplorer 81e334e
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 4ffcad9
fix(wasm-sdk): sign private contact requests with the identity signer
QuantumExplorer 6db333e
fix(sdk): bind the recipient key into a private request's signature
QuantumExplorer 3d510b8
fix(sdk): export private_contact_request_signing_keys
QuantumExplorer 888068a
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer d4efa2e
fix(sdk): validate private requests with dpp and check proved identit…
QuantumExplorer f3f6488
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 9d347a5
fix(wasm-sdk): load a page's contract first and wipe read keys on eve…
QuantumExplorer 473a440
fix(sdk): refuse expired signing keys and refresh a DashPay without t…
QuantumExplorer d15e3b0
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 4a4826a
fix(sdk): keep encryption keys inside their contract bounds and check…
QuantumExplorer 30c8f6a
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 785e493
fix(sdk): give an empty context provider the DashPay it fetches, and …
QuantumExplorer 9ebc1b6
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer b3a0ad3
fix(wasm-dpp2): key the constructor's tokens by position as text, and…
QuantumExplorer e7b8eac
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer f5dde30
fix(wasm-dpp2): refuse tokens for a contract that cannot hold them
QuantumExplorer 0ce4688
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 410b38c
fix(sdk): refuse a scan of another store as DashPay private contact r…
QuantumExplorer 2daee2b
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer ab68754
refactor(dpp): give the document signing levels of a security require…
QuantumExplorer 1bd3788
fix(sdk): read a private contact request only through a key it could …
QuantumExplorer 609f529
fix(sdk): wipe the outgoing viewing key a private contact request is …
QuantumExplorer 5839100
fix(sdk): give a private page reader's context provider the contract …
QuantumExplorer be7fba8
feat(sdk): stream a private document store's pages, many fetched at once
QuantumExplorer b8e41ab
fix(sdk): refuse a private document read below protocol version 15 as…
QuantumExplorer d91c1c6
fix(sdk): name the SDK's protocol version when building a private doc…
QuantumExplorer 0e3f521
fix(wasm-dpp2): refuse tokens set on a data contract that holds none
QuantumExplorer 3f546c0
docs(dpp): say at the batch signing levels why the in-place change ke…
QuantumExplorer e710dd7
docs(sdk): say what the private contact request parser and signing le…
QuantumExplorer 454f25c
test(sdk): check a recipient key holding another point is refused by …
QuantumExplorer 3b68903
test(sdk): pin a private page stream's order and its cursor under a g…
QuantumExplorer 898e8fc
fix(sdk): keep the store a private document scan was read from, and r…
QuantumExplorer 91d8782
fix(sdk): send a private document transition only once the network is…
QuantumExplorer 19ab417
fix(sdk): keep each outgoing viewing key in place as scan senders are…
QuantumExplorer fd3134b
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 3571bb8
fix(wasm-sdk): read private document pages against the contract that …
QuantumExplorer b8780f5
test(wasm-sdk): test the private contact request bindings' conversion…
QuantumExplorer 59e047a
fix(sdk): learn a private store's chunk size only from a page that en…
QuantumExplorer 314d957
fix(sdk): refuse a private contact request scan of a contract whose t…
QuantumExplorer 4d30b82
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer e11ef7c
fix(sdk): keep a newer contract over a registered older one
QuantumExplorer 04a7f96
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer efa0fc8
fix(sdk): complete a private store chunk an older snapshot ended part…
QuantumExplorer baa3092
fix(sdk): gate every type 29 broadcast and refuse it with the structu…
QuantumExplorer 40e4f57
fix(sdk): keep a newer contract in the gRPC context provider, and say…
QuantumExplorer f7fcc44
fix(sdk): report an identity proved before its entry as a retryable s…
QuantumExplorer 80094d0
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer b065ca3
fix(sdk): read a private contact request under an eligible alias of i…
QuantumExplorer 4712db7
fix(sdk): fetch again a private page an older snapshot left empty, th…
QuantumExplorer 8558e83
feat(sdk): schedule a private store's page walk from the chunk size i…
QuantumExplorer 741c972
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 75279c6
test(wasm-sdk): build test pages with the chunk power the SDK page no…
QuantumExplorer e5112af
perf(wasm-sdk): store a private type's contract once a version, not o…
QuantumExplorer 4386ec0
docs(sdk): say that a private request's key expiry is the identity's …
QuantumExplorer 699693f
Merge remote-tracking branch 'origin/feat/sdk-private-documents-send-…
QuantumExplorer f9d669f
fix(sdk-trusted-context-provider): keep a newer known contract over a…
QuantumExplorer 311ae62
fix(sdk): keep a failed refresh as the cause of a private document se…
QuantumExplorer 4e75e27
fix(sdk): read a private page against a newer contract with the type …
QuantumExplorer 235a4f8
fix(sdk): take the network as proven below a version only on a curren…
QuantumExplorer 956e962
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer ecf621d
docs(wasm-sdk): say that a registration keeps a held contract of a hi…
QuantumExplorer 0dc274c
fix(sdk): ask the protocol gate before refusing a private document send
QuantumExplorer 9b8589a
test(drive-abci): export a protocol 15 epoch probe for the SDK's gate…
QuantumExplorer 50658b5
fix(sdk): establish protocol 15 through the gate for DashPay's privat…
QuantumExplorer 6a9fea5
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/was…
QuantumExplorer 84c2b96
feat(platform-version): double a private document store's chunk targe…
QuantumExplorer 52cdd2a
Merge remote-tracking branch 'origin/feat/sdk-private-documents-send-…
QuantumExplorer e083164
Merge remote-tracking branch 'origin/v5.1-dev' into feat/wasm-sdk-pri…
QuantumExplorer c5d08bb
test(drive-abci): expect DashPay v3's private store at chunk power 10…
QuantumExplorer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import * as wasm from '../wasm.js'; | ||
| import type { EvoSDK } from '../sdk.js'; | ||
|
|
||
| /** | ||
| * Private document types (protocol version 15) and DashPay's private contact requests. | ||
| * | ||
| * A private type's documents are fixed-size encrypted entries of a store, in append order, | ||
| * readable a page at a time. A DashPay private contact request is one such entry sealed to the | ||
| * recipient's DashPay key: only the recipient learns it exists, who sent it and what it holds. | ||
| * | ||
| * Appending an entry is paid from the shielded pool, which needs an Orchard proof this SDK | ||
| * cannot make yet (see `ShieldedFacade`): `sealContactRequest` builds the entry, and a wallet | ||
| * that can prove appends it. | ||
| */ | ||
| export class PrivateDocumentsFacade { | ||
| private sdk: EvoSDK; | ||
|
|
||
| constructor(sdk: EvoSDK) { | ||
| this.sdk = sdk; | ||
| } | ||
|
|
||
| /** | ||
| * The proved page of a private type's store from `startPosition`, up to the end of the | ||
| * store's chunk holding it. A reader walks the store by asking again from the position after | ||
| * the page's last entry, until `totalCount`. | ||
| */ | ||
| async entries( | ||
| dataContractId: wasm.IdentifierLike, | ||
| documentTypeName: string, | ||
| startPosition: bigint, | ||
| ): Promise<wasm.PrivateDocumentEntriesPage> { | ||
| const w = await this.sdk.getWasmSdkConnected(); | ||
| return w.getPrivateDocumentEntries(dataContractId, documentTypeName, startPosition); | ||
| } | ||
|
|
||
| /** | ||
| * Seals a DashPay private contact request from the sender's encryption key to one of the | ||
| * recipient's DashPay keys, signed by `options.signer` with one of the sender's signing keys, | ||
| * as its transitions are. | ||
| * | ||
| * @returns The entry, of the type's entry size, to append. | ||
| */ | ||
| async sealContactRequest(options: wasm.SealPrivateContactRequestOptions): Promise<Uint8Array> { | ||
| const w = await this.sdk.getWasmSdkConnected(); | ||
| return w.sealPrivateContactRequest(options); | ||
| } | ||
|
|
||
| /** | ||
| * Reads one page of DashPay's private contact request store for the wallet's identities: the | ||
| * requests to them, each checked against its sender's signing keys, and the requests they | ||
| * sent. It fetches the identities those requests are checked against right after the page, so | ||
| * a node serving both can tell which identities the wallet looked up. Keep `nextPosition` as the cursor once the page is stored, and scan | ||
| * again from it until `isComplete`. | ||
| */ | ||
| async scanContactRequests( | ||
| options: wasm.ScanPrivateContactRequestsOptions, | ||
| ): Promise<wasm.PrivateContactRequestScanResult> { | ||
| const w = await this.sdk.getWasmSdkConnected(); | ||
| return w.scanPrivateContactRequests(options); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
packages/js-evo-sdk/tests/unit/facades/private-documents.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| import type { SinonStub } from 'sinon'; | ||
| import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; | ||
| import { EvoSDK } from '../../../dist/sdk.js'; | ||
|
|
||
| describe('PrivateDocumentsFacade', () => { | ||
| let wasmSdk: wasmSDKPackage.WasmSdk; | ||
| let client: EvoSDK; | ||
|
|
||
| let getPrivateDocumentEntriesStub: SinonStub; | ||
| let sealPrivateContactRequestStub: SinonStub; | ||
| let scanPrivateContactRequestsStub: SinonStub; | ||
|
|
||
| beforeEach(async function setup() { | ||
| await init(); | ||
| const builder = wasmSDKPackage.WasmSdkBuilder.testnet(); | ||
| wasmSdk = await builder.build(); | ||
| client = EvoSDK.fromWasm(wasmSdk); | ||
|
|
||
| getPrivateDocumentEntriesStub = this.sinon | ||
| .stub(wasmSdk, 'getPrivateDocumentEntries') | ||
| .resolves({ entries: [], totalCount: 0n }); | ||
| sealPrivateContactRequestStub = this.sinon | ||
| .stub(wasmSdk, 'sealPrivateContactRequest') | ||
| .resolves(new Uint8Array(589)); | ||
| scanPrivateContactRequestsStub = this.sinon | ||
| .stub(wasmSdk, 'scanPrivateContactRequests') | ||
| .resolves('scan'); | ||
| }); | ||
|
|
||
| describe('entries()', () => { | ||
| it('should forward the contract, type and start position to getPrivateDocumentEntries', async () => { | ||
| const big = 9_007_199_254_740_993n; // > Number.MAX_SAFE_INTEGER | ||
| const result = await client.privateDocuments.entries('contract', 'privateContactRequest', big); | ||
| expect(getPrivateDocumentEntriesStub).to.be.calledOnceWithExactly( | ||
| 'contract', | ||
| 'privateContactRequest', | ||
| big, | ||
| ); | ||
| expect(result).to.deep.equal({ entries: [], totalCount: 0n }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('sealContactRequest()', () => { | ||
| it('should forward the options to sealPrivateContactRequest and return the entry', async () => { | ||
| const options = { recipientKeyId: 2 } as unknown as wasmSDKPackage.SealPrivateContactRequestOptions; | ||
| const entry = await client.privateDocuments.sealContactRequest(options); | ||
| expect(sealPrivateContactRequestStub).to.be.calledOnceWithExactly(options); | ||
| expect(entry).to.have.length(589); | ||
| }); | ||
| }); | ||
|
|
||
| describe('scanContactRequests()', () => { | ||
| it('should forward the options to scanPrivateContactRequests', async () => { | ||
| const options = { startPosition: 0n }; | ||
| const result = await client.privateDocuments.scanContactRequests(options); | ||
| expect(scanPrivateContactRequestsStub).to.be.calledOnceWithExactly(options); | ||
| expect(result).to.equal('scan'); | ||
| }); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.