dash-platform-sdk 1.4.0 → 1.5.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +15 -15
  2. package/bundle.min.js +17 -17
  3. package/package.json +2 -2
  4. package/proto/generated/platform.client.d.ts +70 -0
  5. package/proto/generated/platform.client.js +61 -12
  6. package/proto/generated/platform.d.ts +1025 -0
  7. package/proto/generated/platform.js +2074 -1
  8. package/src/DashPlatformSDK.d.ts +2 -0
  9. package/src/DashPlatformSDK.js +3 -0
  10. package/src/constants.d.ts +1 -0
  11. package/src/constants.js +1 -0
  12. package/src/keyPair/index.d.ts +25 -0
  13. package/src/keyPair/index.js +33 -0
  14. package/src/node/{epochs.d.ts → epochInfos.d.ts} +1 -1
  15. package/src/node/{epochs.js → epochInfos.js} +1 -1
  16. package/src/node/finalizedEpochInfos.d.ts +21 -0
  17. package/src/node/finalizedEpochInfos.js +54 -0
  18. package/src/node/index.d.ts +9 -1
  19. package/src/node/index.js +11 -1
  20. package/src/shielded/createStateTransition.d.ts +3 -0
  21. package/src/shielded/createStateTransition.js +55 -0
  22. package/src/shielded/getMostRecentShieldedAnchor.d.ts +2 -0
  23. package/src/shielded/getMostRecentShieldedAnchor.js +36 -0
  24. package/src/shielded/getShieldedAnchors.d.ts +2 -0
  25. package/src/shielded/getShieldedAnchors.js +36 -0
  26. package/src/shielded/getShieldedEncryptedNotes.d.ts +3 -0
  27. package/src/shielded/getShieldedEncryptedNotes.js +43 -0
  28. package/src/shielded/getShieldedNotesCount.d.ts +2 -0
  29. package/src/shielded/getShieldedNotesCount.js +36 -0
  30. package/src/shielded/getShieldedNullifiers.d.ts +3 -0
  31. package/src/shielded/getShieldedNullifiers.js +40 -0
  32. package/src/shielded/getShieldedPoolState.d.ts +2 -0
  33. package/src/shielded/getShieldedPoolState.js +36 -0
  34. package/src/shielded/index.d.ts +130 -0
  35. package/src/shielded/index.js +186 -0
  36. package/test/unit/KeyPair.spec.js +32 -0
  37. package/test/unit/Node.spec.js +6 -0
  38. package/test/unit/Shielded.spec.d.ts +1 -0
  39. package/test/unit/Shielded.spec.js +236 -0
  40. package/types.d.ts +85 -1
@@ -12,6 +12,7 @@ import { TokensController } from './tokens/index.js';
12
12
  import { VotingController } from './voting/index.js';
13
13
  import { Network } from '../types.js';
14
14
  import { PlatformAddressesController } from './platformAddresses/index.js';
15
+ import { ShieldedController } from './shielded/index.js';
15
16
  export interface GRPCOptions {
16
17
  poolLimit: 5;
17
18
  dapiUrl?: string | string[];
@@ -33,6 +34,7 @@ export declare class DashPlatformSDK {
33
34
  options?: SDKOptions;
34
35
  contestedResources: ContestedResourcesController;
35
36
  platformAddresses: PlatformAddressesController;
37
+ shielded: ShieldedController;
36
38
  stateTransitions: StateTransitionsController;
37
39
  dataContracts: DataContractsController;
38
40
  identities: IdentitiesController;
@@ -11,6 +11,7 @@ import { ContestedResourcesController } from './contestedResources/index.js';
11
11
  import { TokensController } from './tokens/index.js';
12
12
  import { VotingController } from './voting/index.js';
13
13
  import { PlatformAddressesController } from './platformAddresses/index.js';
14
+ import { ShieldedController } from './shielded/index.js';
14
15
  /**
15
16
  * Javascript SDK for that let you interact with a Dash Platform blockchain
16
17
  */
@@ -22,6 +23,7 @@ export class DashPlatformSDK {
22
23
  options;
23
24
  contestedResources;
24
25
  platformAddresses;
26
+ shielded;
25
27
  stateTransitions;
26
28
  dataContracts;
27
29
  identities;
@@ -65,6 +67,7 @@ export class DashPlatformSDK {
65
67
  this.grpcPool = grpcPool;
66
68
  this.contestedResources = new ContestedResourcesController(grpcPool);
67
69
  this.platformAddresses = new PlatformAddressesController(grpcPool);
70
+ this.shielded = new ShieldedController(grpcPool);
68
71
  this.stateTransitions = new StateTransitionsController(grpcPool);
69
72
  this.dataContracts = new DataContractsController(grpcPool);
70
73
  this.identities = new IdentitiesController(grpcPool);
@@ -3,6 +3,7 @@ import { PlatformVersionWASM } from 'pshenmic-dpp';
3
3
  * Default amount of documents to retrieve from DAPI
4
4
  */
5
5
  export declare const DAPI_DEFAULT_LIMIT = 100;
6
+ export declare const SHIELDED_MAX_NOTES_PER_QUERY = 8192;
6
7
  export declare const HALVING_INTERVAL = 210240;
7
8
  export declare const TESTNET_ACTIVATION_HEIGHT = 1066900;
8
9
  export declare const MAINNET_ACTIVATION_HEIGHT = 2128896;
package/src/constants.js CHANGED
@@ -3,6 +3,7 @@ import { PlatformVersionWASM } from 'pshenmic-dpp';
3
3
  * Default amount of documents to retrieve from DAPI
4
4
  */
5
5
  export const DAPI_DEFAULT_LIMIT = 100;
6
+ export const SHIELDED_MAX_NOTES_PER_QUERY = 8192;
6
7
  export const HALVING_INTERVAL = 210240;
7
8
  export const TESTNET_ACTIVATION_HEIGHT = 1066900;
8
9
  export const MAINNET_ACTIVATION_HEIGHT = 2128896;
@@ -1,5 +1,6 @@
1
1
  import { HDKey } from '@scure/bip32';
2
2
  import { Network } from '../../types.js';
3
+ import { OrchardAddressWASM } from 'pshenmic-dpp';
3
4
  /**
4
5
  * Collection of functions to work with private keys and seed phrases
5
6
  *
@@ -64,4 +65,28 @@ export declare class KeyPairController {
64
65
  * @returns {string}
65
66
  */
66
67
  p2pkhAddress(publicKey: Uint8Array, network: Network): string;
68
+ /**
69
+ * Derives a shielded (Orchard) address from a BIP-39 seed via ZIP-32
70
+ * (m/32'/coinType'/account').
71
+ *
72
+ * @param seed {Uint8Array} - BIP-39 seed bytes
73
+ * @param network {Network} - network (selects the SLIP-44 coin type)
74
+ * @param account {number} - ZIP-32 account index
75
+ * @param diversifierIndex {number=} - optional diversifier index
76
+ *
77
+ * @returns {OrchardAddressWASM}
78
+ */
79
+ deriveShieldedAddress(seed: Uint8Array, network: Network, account: number, diversifierIndex?: number): OrchardAddressWASM;
80
+ /**
81
+ * Derives the sender's Orchard outgoing viewing key (OVK, 32 bytes) from a
82
+ * BIP-39 seed via ZIP-32 (m/32'/coinType'/account'). Used to recover the
83
+ * outgoing notes a wallet sent.
84
+ *
85
+ * @param seed {Uint8Array} - BIP-39 seed bytes
86
+ * @param network {Network} - network (selects the SLIP-44 coin type)
87
+ * @param account {number} - ZIP-32 account index
88
+ *
89
+ * @returns {Uint8Array} 32-byte outgoing viewing key
90
+ */
91
+ deriveShieldedOutgoingViewingKey(seed: Uint8Array, network: Network, account: number): Uint8Array;
67
92
  }
@@ -3,6 +3,7 @@ import mnemonicToSeed from './mnemonicToSeed.js';
3
3
  import deriveChild from './deriveChild.js';
4
4
  import derivePath from './derivePath.js';
5
5
  import { p2pkh } from '@scure/btc-signer';
6
+ import { OrchardAddressWASM, orchardOvkFromSeed } from 'pshenmic-dpp';
6
7
  const DASH_VERSIONS = {
7
8
  mainnet: { pubKeyHash: 0x4c, scriptHash: 0x10, bech32: 'dc', wif: 0xcc, private: 0x0488ade4, public: 0x0488b21e },
8
9
  testnet: { pubKeyHash: 0x8c, scriptHash: 0x13, bech32: 'dc', wif: 0xef, private: 0x04358394, public: 0x043587cf }
@@ -86,4 +87,36 @@ export class KeyPairController {
86
87
  const P2PKH = p2pkh(publicKey, DASH_VERSIONS[network]);
87
88
  return P2PKH.address;
88
89
  }
90
+ /**
91
+ * Derives a shielded (Orchard) address from a BIP-39 seed via ZIP-32
92
+ * (m/32'/coinType'/account').
93
+ *
94
+ * @param seed {Uint8Array} - BIP-39 seed bytes
95
+ * @param network {Network} - network (selects the SLIP-44 coin type)
96
+ * @param account {number} - ZIP-32 account index
97
+ * @param diversifierIndex {number=} - optional diversifier index
98
+ *
99
+ * @returns {OrchardAddressWASM}
100
+ */
101
+ deriveShieldedAddress(seed, network, account, diversifierIndex) {
102
+ // SLIP-44 coin type: 5 = Dash mainnet, 1 = testnets. Orchard derives via ZIP-32
103
+ const coinType = network === 'mainnet' ? 5 : 1;
104
+ return OrchardAddressWASM.fromSeed(seed, coinType, account, diversifierIndex);
105
+ }
106
+ /**
107
+ * Derives the sender's Orchard outgoing viewing key (OVK, 32 bytes) from a
108
+ * BIP-39 seed via ZIP-32 (m/32'/coinType'/account'). Used to recover the
109
+ * outgoing notes a wallet sent.
110
+ *
111
+ * @param seed {Uint8Array} - BIP-39 seed bytes
112
+ * @param network {Network} - network (selects the SLIP-44 coin type)
113
+ * @param account {number} - ZIP-32 account index
114
+ *
115
+ * @returns {Uint8Array} 32-byte outgoing viewing key
116
+ */
117
+ deriveShieldedOutgoingViewingKey(seed, network, account) {
118
+ // SLIP-44 coin type: 5 = Dash mainnet, 1 = testnets. Orchard derives via ZIP-32
119
+ const coinType = network === 'mainnet' ? 5 : 1;
120
+ return orchardOvkFromSeed(seed, coinType, account);
121
+ }
89
122
  }
@@ -7,4 +7,4 @@ export interface EpochInfo {
7
7
  feeMultiplier: bigint;
8
8
  protocolVersion: 9;
9
9
  }
10
- export default function epochs(grpcPool: GRPCConnectionPool, count: number, ascending: boolean, start?: number): Promise<EpochInfo[]>;
10
+ export default function epochInfos(grpcPool: GRPCConnectionPool, count: number, ascending: boolean, start?: number): Promise<EpochInfo[]>;
@@ -5,7 +5,7 @@ import bytesToHex from '../utils/bytesToHex.js';
5
5
  import verifyTenderdashProof from '../utils/verifyTenderdashProof.js';
6
6
  import { UInt32Value } from '../../proto/generated/google/protobuf/wrappers.js';
7
7
  import { LATEST_PLATFORM_VERSION } from '../constants.js';
8
- export default async function epochs(grpcPool, count, ascending, start) {
8
+ export default async function epochInfos(grpcPool, count, ascending, start) {
9
9
  const getEpochsInfoRequest = GetEpochsInfoRequest.create({
10
10
  version: {
11
11
  oneofKind: 'v0',
@@ -0,0 +1,21 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ import { IdentifierWASM } from 'pshenmic-dpp';
3
+ export interface FinalizedEpochInfo {
4
+ epochIndex: number;
5
+ firstBlockTime: Date;
6
+ firstBlockHeight: bigint;
7
+ totalBlocksInEpoch: bigint;
8
+ firstCoreBlockHeight: number;
9
+ nextEpochStartCoreBlockHeight: number;
10
+ totalProcessingFees: bigint;
11
+ totalDistributedStorageFees: bigint;
12
+ totalCreatedStorageFees: bigint;
13
+ coreBlockRewards: bigint;
14
+ blockProposers: {
15
+ proposer: IdentifierWASM;
16
+ count: bigint;
17
+ }[];
18
+ feeMultiplier: bigint;
19
+ protocolVersion: number;
20
+ }
21
+ export default function getFinalizedEpochsInfo(grpcPool: GRPCConnectionPool, startEpochIndex: number, startEpochIndexIncluded: boolean, endEpochIndex: number, endEpochIndexIncluded: boolean): Promise<FinalizedEpochInfo[]>;
@@ -0,0 +1,54 @@
1
+ import { GetFinalizedEpochInfosRequest } from '../../proto/generated/platform.js';
2
+ import { verifyFinalizedEpochInfosProof } from 'pshenmic-dpp';
3
+ import { getQuorumPublicKey } from '../utils/getQuorumPublicKey.js';
4
+ import bytesToHex from '../utils/bytesToHex.js';
5
+ import verifyTenderdashProof from '../utils/verifyTenderdashProof.js';
6
+ import { LATEST_PLATFORM_VERSION } from '../constants.js';
7
+ export default async function getFinalizedEpochsInfo(grpcPool, startEpochIndex, startEpochIndexIncluded, endEpochIndex, endEpochIndexIncluded) {
8
+ const getEpochsInfoRequest = GetFinalizedEpochInfosRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ startEpochIndex,
13
+ startEpochIndexIncluded,
14
+ endEpochIndex,
15
+ endEpochIndexIncluded,
16
+ prove: true
17
+ }
18
+ }
19
+ });
20
+ const { response } = await grpcPool.getClient().getFinalizedEpochInfos(getEpochsInfoRequest);
21
+ const { version } = response;
22
+ if (version.oneofKind !== 'v0') {
23
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
24
+ }
25
+ const { v0 } = version;
26
+ if (v0.result.oneofKind !== 'proof') {
27
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
28
+ }
29
+ const { result: { proof }, metadata } = v0;
30
+ if (metadata == null) {
31
+ throw new Error('Metadata not found');
32
+ }
33
+ const { rootHash, epochInfos } = verifyFinalizedEpochInfosProof(proof.grovedbProof, startEpochIndex, startEpochIndexIncluded, endEpochIndex, endEpochIndexIncluded, LATEST_PLATFORM_VERSION);
34
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
35
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
36
+ if (!verify) {
37
+ throw new Error('Failed to verify query');
38
+ }
39
+ return epochInfos.map(info => ({
40
+ epochIndex: info.epochIndex,
41
+ firstBlockTime: info.firstBlockTime,
42
+ firstBlockHeight: info.firstBlockHeight,
43
+ totalBlocksInEpoch: info.totalBlocksInEpoch,
44
+ firstCoreBlockHeight: info.firstCoreBlockHeight,
45
+ nextEpochStartCoreBlockHeight: info.nextEpochStartCoreBlockHeight,
46
+ totalProcessingFees: info.totalProcessingFees,
47
+ totalDistributedStorageFees: info.totalDistributedStorageFees,
48
+ totalCreatedStorageFees: info.totalCreatedStorageFees,
49
+ coreBlockRewards: info.coreBlockRewards,
50
+ blockProposers: info.blockProposers,
51
+ feeMultiplier: info.feeMultiplierPermille,
52
+ protocolVersion: info.protocolVersion
53
+ }));
54
+ }
@@ -1,6 +1,7 @@
1
1
  import GRPCConnectionPool from '../grpcConnectionPool.js';
2
2
  import { NodeStatus } from '../../types.js';
3
- import { EpochInfo } from './epochs.js';
3
+ import { EpochInfo } from './epochInfos.js';
4
+ import { FinalizedEpochInfo } from './finalizedEpochInfos.js';
4
5
  /**
5
6
  * Node controller for requesting information about DAPI node
6
7
  *
@@ -30,4 +31,11 @@ export declare class NodeController {
30
31
  * @return {Promise<EpochInfo[]>}
31
32
  */
32
33
  getEpochsInfo(count: number, ascending: boolean, start?: number): Promise<EpochInfo[]>;
34
+ /**
35
+ * Retrieves an finalized info about epochs
36
+ * Includes information about first block height, time, fee multiplier, number
37
+ *
38
+ * @return {Promise<FinalizedEpochInfo[]>}
39
+ */
40
+ getFinalizedEpochsInfo(startEpochIndex: number, startEpochIndexIncluded: boolean, endEpochIndex: number, endEpochIndexIncluded: boolean): Promise<FinalizedEpochInfo[]>;
33
41
  }
package/src/node/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import getStatus from './status.js';
2
- import getEpochsInfo from './epochs.js';
2
+ import getEpochsInfo from './epochInfos.js';
3
+ import getFinalizedEpochsInfo from './finalizedEpochInfos.js';
3
4
  import getTotalCredits from './totalCredits.js';
4
5
  /**
5
6
  * Node controller for requesting information about DAPI node
@@ -38,4 +39,13 @@ export class NodeController {
38
39
  async getEpochsInfo(count, ascending, start) {
39
40
  return await getEpochsInfo(this.grpcPool, count, ascending, start);
40
41
  }
42
+ /**
43
+ * Retrieves an finalized info about epochs
44
+ * Includes information about first block height, time, fee multiplier, number
45
+ *
46
+ * @return {Promise<FinalizedEpochInfo[]>}
47
+ */
48
+ async getFinalizedEpochsInfo(startEpochIndex, startEpochIndexIncluded, endEpochIndex, endEpochIndexIncluded) {
49
+ return await getFinalizedEpochsInfo(this.grpcPool, startEpochIndex, startEpochIndexIncluded, endEpochIndex, endEpochIndexIncluded);
50
+ }
41
51
  }
@@ -0,0 +1,3 @@
1
+ import { ShieldedBuilderWASM, StateTransitionWASM } from 'pshenmic-dpp';
2
+ import { ShieldedTransitionParamsMap, ShieldedTransitionType } from '../../types.js';
3
+ export default function createStateTransition<K extends ShieldedTransitionType>(builder: ShieldedBuilderWASM, type: K, params: ShieldedTransitionParamsMap[K]): StateTransitionWASM;
@@ -0,0 +1,55 @@
1
+ import { IdentityCreateFromShieldedPoolTransitionWASM, ShieldedBuilderWASM, ShieldedWithdrawalResultWASM, StateTransitionWASM } from 'pshenmic-dpp';
2
+ import { LATEST_PLATFORM_VERSION } from '../constants.js';
3
+ const shieldedTransitionsMap = {
4
+ shield: {
5
+ method: ShieldedBuilderWASM.prototype.shield,
6
+ arguments: ['recipient', 'shieldAmount', 'inputs', 'privateKeys', 'feeStrategy', 'userFeeIncrease', 'memo'],
7
+ optionalArguments: ['senderOvk']
8
+ },
9
+ shieldFromAssetLock: {
10
+ method: ShieldedBuilderWASM.prototype.shieldFromAssetLock,
11
+ arguments: ['recipient', 'shieldAmount', 'assetLockProof', 'privateKey', 'memo', 'dummyOutputs'],
12
+ optionalArguments: ['senderOvk', 'surplusOutput']
13
+ },
14
+ shieldedWithdrawal: {
15
+ method: ShieldedBuilderWASM.prototype.shieldedWithdrawal,
16
+ arguments: ['spends', 'withdrawalAmount', 'outputScript', 'coreFeePerByte', 'pooling', 'changeAddress', 'seed', 'coinType', 'account', 'anchor', 'memo'],
17
+ optionalArguments: []
18
+ },
19
+ unshield: {
20
+ method: ShieldedBuilderWASM.prototype.unshield,
21
+ arguments: ['spends', 'outputAddress', 'unshieldAmount', 'changeAddress', 'seed', 'coinType', 'account', 'anchor', 'memo'],
22
+ optionalArguments: []
23
+ },
24
+ shieldedTransfer: {
25
+ method: ShieldedBuilderWASM.prototype.shieldedTransfer,
26
+ arguments: ['spends', 'recipient', 'transferAmount', 'changeAddress', 'seed', 'coinType', 'account', 'anchor', 'memo'],
27
+ optionalArguments: []
28
+ },
29
+ identityCreateFromShieldedPool: {
30
+ method: ShieldedBuilderWASM.prototype.identityCreateFromShieldedPool,
31
+ arguments: ['publicKeys', 'privateKeys', 'denomination', 'sendToAddressOnCreationFailure', 'spends', 'changeAddress', 'seed', 'coinType', 'account', 'anchor', 'memo'],
32
+ optionalArguments: []
33
+ }
34
+ };
35
+ export default function createStateTransition(builder, type, params) {
36
+ const { method: builderMethod, arguments: classArguments, optionalArguments } = shieldedTransitionsMap[type];
37
+ if (builderMethod == null) {
38
+ throw new Error(`Unimplemented shielded transition type: ${type}`);
39
+ }
40
+ const [missingArgument] = classArguments
41
+ .filter((classArgument) => params[classArgument] == null);
42
+ if (missingArgument != null) {
43
+ throw new Error(`Shielded transition param "${missingArgument}" is missing`);
44
+ }
45
+ const transitionParams = classArguments.concat(optionalArguments).map((classArgument) => params[classArgument]);
46
+ const result = builderMethod.apply(builder, [...transitionParams, params.platformVersion ?? LATEST_PLATFORM_VERSION]);
47
+ if (result instanceof StateTransitionWASM) {
48
+ return result;
49
+ }
50
+ if (result instanceof ShieldedWithdrawalResultWASM) {
51
+ return result.stateTransition;
52
+ }
53
+ const { denomination, sendToAddressOnCreationFailure } = params;
54
+ return new IdentityCreateFromShieldedPoolTransitionWASM(result.publicKeys, denomination, result.actions, result.anchor, result.proof, result.bindingsSignature, sendToAddressOnCreationFailure, result.identityId).toStateTransition();
55
+ }
@@ -0,0 +1,2 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ export default function getMostRecentShieldedAnchor(grpcPool: GRPCConnectionPool): Promise<Uint8Array | undefined>;
@@ -0,0 +1,36 @@
1
+ import { GetMostRecentShieldedAnchorRequest } from '../../proto/generated/platform.js';
2
+ import { verifyMostRecentShieldedAnchorProof } from "pshenmic-dpp";
3
+ import { LATEST_PLATFORM_VERSION } from "../constants.js";
4
+ import { getQuorumPublicKey } from "../utils/getQuorumPublicKey.js";
5
+ import bytesToHex from "../utils/bytesToHex.js";
6
+ import verifyTenderdashProof from "../utils/verifyTenderdashProof.js";
7
+ export default async function getMostRecentShieldedAnchor(grpcPool) {
8
+ const getMostRecentShieldedAnchorRequest = GetMostRecentShieldedAnchorRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ prove: true
13
+ }
14
+ }
15
+ });
16
+ const { response } = await grpcPool.getClient().getMostRecentShieldedAnchor(getMostRecentShieldedAnchorRequest);
17
+ const { version } = response;
18
+ if (version.oneofKind !== 'v0') {
19
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
20
+ }
21
+ const { v0 } = version;
22
+ if (v0.result.oneofKind !== 'proof') {
23
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
24
+ }
25
+ const { result: { proof }, metadata } = v0;
26
+ if (metadata == null) {
27
+ throw new Error('Metadata not found');
28
+ }
29
+ const { rootHash, anchor } = verifyMostRecentShieldedAnchorProof(proof.grovedbProof, true, LATEST_PLATFORM_VERSION);
30
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
31
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
32
+ if (!verify) {
33
+ throw new Error('Failed to verify query');
34
+ }
35
+ return anchor;
36
+ }
@@ -0,0 +1,2 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ export default function getShieldedAnchors(grpcPool: GRPCConnectionPool): Promise<Uint8Array[]>;
@@ -0,0 +1,36 @@
1
+ import { GetShieldedAnchorsRequest } from '../../proto/generated/platform.js';
2
+ import { verifyShieldedAnchorsProof } from "pshenmic-dpp";
3
+ import { LATEST_PLATFORM_VERSION } from "../constants.js";
4
+ import { getQuorumPublicKey } from "../utils/getQuorumPublicKey.js";
5
+ import bytesToHex from "../utils/bytesToHex.js";
6
+ import verifyTenderdashProof from "../utils/verifyTenderdashProof.js";
7
+ export default async function getShieldedAnchors(grpcPool) {
8
+ const getShieldedAnchorsRequest = GetShieldedAnchorsRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ prove: true
13
+ }
14
+ }
15
+ });
16
+ const { response } = await grpcPool.getClient().getShieldedAnchors(getShieldedAnchorsRequest);
17
+ const { version } = response;
18
+ if (version.oneofKind !== 'v0') {
19
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
20
+ }
21
+ const { v0 } = version;
22
+ if (v0.result.oneofKind !== 'proof') {
23
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
24
+ }
25
+ const { result: { proof }, metadata } = v0;
26
+ if (metadata == null) {
27
+ throw new Error('Metadata not found');
28
+ }
29
+ const { rootHash, anchors } = verifyShieldedAnchorsProof(proof.grovedbProof, true, LATEST_PLATFORM_VERSION);
30
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
31
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
32
+ if (!verify) {
33
+ throw new Error('Failed to verify query');
34
+ }
35
+ return anchors;
36
+ }
@@ -0,0 +1,3 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ import { ShieldedEncryptedNote } from '../../types.js';
3
+ export default function getShieldedEncryptedNotes(grpcPool: GRPCConnectionPool, startIndex: bigint, count: number): Promise<ShieldedEncryptedNote[]>;
@@ -0,0 +1,43 @@
1
+ import { GetShieldedEncryptedNotesRequest } from '../../proto/generated/platform.js';
2
+ import { verifyShieldedEncryptedNotesProof } from "pshenmic-dpp";
3
+ import { LATEST_PLATFORM_VERSION, SHIELDED_MAX_NOTES_PER_QUERY } from "../constants.js";
4
+ import { getQuorumPublicKey } from "../utils/getQuorumPublicKey.js";
5
+ import bytesToHex from "../utils/bytesToHex.js";
6
+ import verifyTenderdashProof from "../utils/verifyTenderdashProof.js";
7
+ export default async function getShieldedEncryptedNotes(grpcPool, startIndex, count) {
8
+ const getShieldedEncryptedNotesRequest = GetShieldedEncryptedNotesRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ startIndex: startIndex.toString(),
13
+ count,
14
+ prove: true
15
+ }
16
+ }
17
+ });
18
+ const { response } = await grpcPool.getClient().getShieldedEncryptedNotes(getShieldedEncryptedNotesRequest);
19
+ const { version } = response;
20
+ if (version.oneofKind !== 'v0') {
21
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
22
+ }
23
+ const { v0 } = version;
24
+ if (v0.result.oneofKind !== 'proof') {
25
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
26
+ }
27
+ const { result: { proof }, metadata } = v0;
28
+ if (metadata == null) {
29
+ throw new Error('Metadata not found');
30
+ }
31
+ const { rootHash, notes } = verifyShieldedEncryptedNotesProof(proof.grovedbProof, startIndex, count, SHIELDED_MAX_NOTES_PER_QUERY, true, LATEST_PLATFORM_VERSION);
32
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
33
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
34
+ if (!verify) {
35
+ throw new Error('Failed to verify query');
36
+ }
37
+ return notes.map(note => ({
38
+ nullifier: note.nullifier,
39
+ cmx: note.cmx,
40
+ encryptedNote: note.encryptedNote,
41
+ cvNet: note.cvNet
42
+ }));
43
+ }
@@ -0,0 +1,2 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ export default function getShieldedNotesCount(grpcPool: GRPCConnectionPool): Promise<bigint | undefined>;
@@ -0,0 +1,36 @@
1
+ import { GetShieldedNotesCountRequest } from '../../proto/generated/platform.js';
2
+ import { verifyShieldedNotesCountProof } from "pshenmic-dpp";
3
+ import { LATEST_PLATFORM_VERSION } from "../constants.js";
4
+ import { getQuorumPublicKey } from "../utils/getQuorumPublicKey.js";
5
+ import bytesToHex from "../utils/bytesToHex.js";
6
+ import verifyTenderdashProof from "../utils/verifyTenderdashProof.js";
7
+ export default async function getShieldedNotesCount(grpcPool) {
8
+ const getShieldedNotesCountRequest = GetShieldedNotesCountRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ prove: true
13
+ }
14
+ }
15
+ });
16
+ const { response } = await grpcPool.getClient().getShieldedNotesCount(getShieldedNotesCountRequest);
17
+ const { version } = response;
18
+ if (version.oneofKind !== 'v0') {
19
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
20
+ }
21
+ const { v0 } = version;
22
+ if (v0.result.oneofKind !== 'proof') {
23
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
24
+ }
25
+ const { result: { proof }, metadata } = v0;
26
+ if (metadata == null) {
27
+ throw new Error('Metadata not found');
28
+ }
29
+ const { rootHash, count } = verifyShieldedNotesCountProof(proof.grovedbProof, true, LATEST_PLATFORM_VERSION);
30
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
31
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
32
+ if (!verify) {
33
+ throw new Error('Failed to verify query');
34
+ }
35
+ return count;
36
+ }
@@ -0,0 +1,3 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ import { ShieldedNullifierStatus } from '../../types.js';
3
+ export default function getShieldedNullifiers(grpcPool: GRPCConnectionPool, nullifiers: Uint8Array[]): Promise<ShieldedNullifierStatus[]>;
@@ -0,0 +1,40 @@
1
+ import { GetShieldedNullifiersRequest } from '../../proto/generated/platform.js';
2
+ import { verifyShieldedNullifiersProof } from "pshenmic-dpp";
3
+ import { LATEST_PLATFORM_VERSION } from "../constants.js";
4
+ import { getQuorumPublicKey } from "../utils/getQuorumPublicKey.js";
5
+ import bytesToHex from "../utils/bytesToHex.js";
6
+ import verifyTenderdashProof from "../utils/verifyTenderdashProof.js";
7
+ export default async function getShieldedNullifiers(grpcPool, nullifiers) {
8
+ const getShieldedNullifiersRequest = GetShieldedNullifiersRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ nullifiers,
13
+ prove: true
14
+ }
15
+ }
16
+ });
17
+ const { response } = await grpcPool.getClient().getShieldedNullifiers(getShieldedNullifiersRequest);
18
+ const { version } = response;
19
+ if (version.oneofKind !== 'v0') {
20
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
21
+ }
22
+ const { v0 } = version;
23
+ if (v0.result.oneofKind !== 'proof') {
24
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
25
+ }
26
+ const { result: { proof }, metadata } = v0;
27
+ if (metadata == null) {
28
+ throw new Error('Metadata not found');
29
+ }
30
+ const { rootHash, nullifiers: nullifiersStatuses } = verifyShieldedNullifiersProof(proof.grovedbProof, nullifiers, true, LATEST_PLATFORM_VERSION);
31
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
32
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
33
+ if (!verify) {
34
+ throw new Error('Failed to verify query');
35
+ }
36
+ return nullifiersStatuses.map(entry => ({
37
+ nullifier: entry.nullifier,
38
+ isSpent: entry.isSpent
39
+ }));
40
+ }
@@ -0,0 +1,2 @@
1
+ import GRPCConnectionPool from '../grpcConnectionPool.js';
2
+ export default function getShieldedPoolState(grpcPool: GRPCConnectionPool): Promise<bigint | undefined>;
@@ -0,0 +1,36 @@
1
+ import { GetShieldedPoolStateRequest } from '../../proto/generated/platform.js';
2
+ import { getQuorumPublicKey } from "../utils/getQuorumPublicKey.js";
3
+ import bytesToHex from "../utils/bytesToHex.js";
4
+ import verifyTenderdashProof from "../utils/verifyTenderdashProof.js";
5
+ import { verifyShieldedPoolStateProof } from "pshenmic-dpp";
6
+ import { LATEST_PLATFORM_VERSION } from "../constants.js";
7
+ export default async function getShieldedPoolState(grpcPool) {
8
+ const getShieldedPoolStateRequest = GetShieldedPoolStateRequest.create({
9
+ version: {
10
+ oneofKind: 'v0',
11
+ v0: {
12
+ prove: true
13
+ }
14
+ }
15
+ });
16
+ const { response } = await grpcPool.getClient().getShieldedPoolState(getShieldedPoolStateRequest);
17
+ const { version } = response;
18
+ if (version.oneofKind !== 'v0') {
19
+ throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
20
+ }
21
+ const { v0 } = version;
22
+ if (v0.result.oneofKind !== 'proof') {
23
+ throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
24
+ }
25
+ const { result: { proof }, metadata } = v0;
26
+ if (metadata == null) {
27
+ throw new Error('Metadata not found');
28
+ }
29
+ const { rootHash, totalBalance } = verifyShieldedPoolStateProof(proof.grovedbProof, true, LATEST_PLATFORM_VERSION);
30
+ const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
31
+ const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
32
+ if (!verify) {
33
+ throw new Error('Failed to verify query');
34
+ }
35
+ return totalBalance;
36
+ }