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.
- package/README.md +15 -15
- package/bundle.min.js +17 -17
- package/package.json +2 -2
- package/proto/generated/platform.client.d.ts +70 -0
- package/proto/generated/platform.client.js +61 -12
- package/proto/generated/platform.d.ts +1025 -0
- package/proto/generated/platform.js +2074 -1
- package/src/DashPlatformSDK.d.ts +2 -0
- package/src/DashPlatformSDK.js +3 -0
- package/src/constants.d.ts +1 -0
- package/src/constants.js +1 -0
- package/src/keyPair/index.d.ts +25 -0
- package/src/keyPair/index.js +33 -0
- package/src/node/{epochs.d.ts → epochInfos.d.ts} +1 -1
- package/src/node/{epochs.js → epochInfos.js} +1 -1
- package/src/node/finalizedEpochInfos.d.ts +21 -0
- package/src/node/finalizedEpochInfos.js +54 -0
- package/src/node/index.d.ts +9 -1
- package/src/node/index.js +11 -1
- package/src/shielded/createStateTransition.d.ts +3 -0
- package/src/shielded/createStateTransition.js +55 -0
- package/src/shielded/getMostRecentShieldedAnchor.d.ts +2 -0
- package/src/shielded/getMostRecentShieldedAnchor.js +36 -0
- package/src/shielded/getShieldedAnchors.d.ts +2 -0
- package/src/shielded/getShieldedAnchors.js +36 -0
- package/src/shielded/getShieldedEncryptedNotes.d.ts +3 -0
- package/src/shielded/getShieldedEncryptedNotes.js +43 -0
- package/src/shielded/getShieldedNotesCount.d.ts +2 -0
- package/src/shielded/getShieldedNotesCount.js +36 -0
- package/src/shielded/getShieldedNullifiers.d.ts +3 -0
- package/src/shielded/getShieldedNullifiers.js +40 -0
- package/src/shielded/getShieldedPoolState.d.ts +2 -0
- package/src/shielded/getShieldedPoolState.js +36 -0
- package/src/shielded/index.d.ts +130 -0
- package/src/shielded/index.js +186 -0
- package/test/unit/KeyPair.spec.js +32 -0
- package/test/unit/Node.spec.js +6 -0
- package/test/unit/Shielded.spec.d.ts +1 -0
- package/test/unit/Shielded.spec.js +236 -0
- package/types.d.ts +85 -1
package/src/DashPlatformSDK.d.ts
CHANGED
|
@@ -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;
|
package/src/DashPlatformSDK.js
CHANGED
|
@@ -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);
|
package/src/constants.d.ts
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 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;
|
package/src/keyPair/index.d.ts
CHANGED
|
@@ -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
|
}
|
package/src/keyPair/index.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
+
}
|
package/src/node/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import GRPCConnectionPool from '../grpcConnectionPool.js';
|
|
2
2
|
import { NodeStatus } from '../../types.js';
|
|
3
|
-
import { EpochInfo } from './
|
|
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 './
|
|
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,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,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,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,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,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,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
|
+
}
|