dash-platform-sdk 1.3.0-dev.5 → 1.3.0-dev.6
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/bundle.min.js +17 -17
- package/index.js +2 -0
- package/package.json +4 -4
- package/proto/generated/google/protobuf/wrappers.js +615 -0
- package/proto/generated/platform.client.js +175 -0
- package/proto/generated/platform.js +8277 -0
- package/src/DashPlatformSDK.js +101 -0
- package/src/constants.js +10 -0
- package/src/contestedResources/createStateTransition.js +6 -0
- package/src/contestedResources/getContestedResourceVoteState.js +72 -0
- package/src/contestedResources/index.js +30 -0
- package/src/dataContracts/create.js +11 -0
- package/src/dataContracts/createStateTransition.js +19 -0
- package/src/dataContracts/getDataContractByIdentifier.js +44 -0
- package/src/dataContracts/index.js +57 -0
- package/src/documents/create.js +4 -0
- package/src/documents/createStateTransition.js +52 -0
- package/src/documents/index.js +83 -0
- package/src/documents/query.js +62 -0
- package/src/grpcConnectionPool.js +79 -0
- package/src/identities/createStateTransition.js +34 -0
- package/src/identities/getIdentityBalance.js +40 -0
- package/src/identities/getIdentityByIdentifier.js +40 -0
- package/src/identities/getIdentityByNonUniquePublicKeyHash.js +44 -0
- package/src/identities/getIdentityByPublicKeyHash.js +40 -0
- package/src/identities/getIdentityContractNonce.js +43 -0
- package/src/identities/getIdentityNonce.js +41 -0
- package/src/identities/getIdentityPublicKeys.js +47 -0
- package/src/identities/index.js +141 -0
- package/src/keyPair/deriveChild.js +3 -0
- package/src/keyPair/derivePath.js +3 -0
- package/src/keyPair/index.js +89 -0
- package/src/keyPair/mnemonicToSeed.js +4 -0
- package/src/names/index.js +102 -0
- package/src/names/registerName.js +64 -0
- package/src/names/searchByIdentity.js +5 -0
- package/src/names/searchByName.js +16 -0
- package/src/names/testNameContested.js +3 -0
- package/src/names/validateName.js +11 -0
- package/src/node/epochs.js +46 -0
- package/src/node/index.js +43 -0
- package/src/node/status.js +41 -0
- package/src/node/totalCredits.js +35 -0
- package/src/signer/AbstractSigner.js +1 -0
- package/src/signer/PrivateKeySigner.d.ts +0 -0
- package/src/signer/PrivateKeySigner.js +64 -0
- package/src/signer/setSigner.js +5 -0
- package/src/stateTransitions/broadcast.js +10 -0
- package/src/stateTransitions/index.js +34 -0
- package/src/stateTransitions/waitForStateTransitionResult.js +8 -0
- package/src/tokens/createStateTransition.js +67 -0
- package/src/tokens/getIdentitiesTokenBalances.js +43 -0
- package/src/tokens/getIdentityTokensBalances.js +43 -0
- package/src/tokens/getTokenContractInfo.js +43 -0
- package/src/tokens/getTokenDirectPurchasePrices.js +40 -0
- package/src/tokens/getTokenTotalSupply.js +41 -0
- package/src/tokens/index.js +108 -0
- package/src/types.js +15 -0
- package/src/utils/base58ToBytes.js +4 -0
- package/src/utils/bytesToHex.js +3 -0
- package/src/utils/bytesToTypedArray.js +3 -0
- package/src/utils/calculateMsgHash.js +31 -0
- package/src/utils/calculateSignHash.js +8 -0
- package/src/utils/calculateStateIdHash.js +10 -0
- package/src/utils/convertToHomographSafeChars.js +11 -0
- package/src/utils/createVoterIdentityId.js +13 -0
- package/src/utils/getEvonodeList.js +12 -0
- package/src/utils/getQuorumPublicKey.js +18 -0
- package/src/utils/getRandomArrayItem.js +3 -0
- package/src/utils/getRandomBytes.js +4 -0
- package/src/utils/hexToBytes.js +3 -0
- package/src/utils/index.js +61 -0
- package/src/utils/indexBytesToString.js +4 -0
- package/src/utils/sha256.js +15 -0
- package/src/utils/signHash.js +22 -0
- package/src/utils/signRequestId.js +19 -0
- package/src/utils/sleep.js +3 -0
- package/src/utils/stringToIndexValueBytes.js +10 -0
- package/src/utils/verifyTenderdashProof.js +26 -0
- package/src/voting/createStateTransition.js +6 -0
- package/src/voting/createVote.js +5 -0
- package/src/voting/index.js +55 -0
- package/test/unit/ContestedResources.spec.js +259 -0
- package/test/unit/DataContract.spec.js +75 -0
- package/test/unit/Document.spec.js +109 -0
- package/test/unit/Identity.spec.js +232 -0
- package/test/unit/KeyPair.spec.js +34 -0
- package/test/unit/Names.spec.js +33 -0
- package/test/unit/Node.spec.js +58 -0
- package/test/unit/SDK.spec.js +10 -0
- package/test/unit/Tokens.spec.js +121 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { IdentifierWASM, PlatformVersionWASM, verifyTokensBalancesForIdentityProof } from 'pshenmic-dpp';
|
|
2
|
+
import { GetIdentityTokenBalancesRequest } from '../../proto/generated/platform';
|
|
3
|
+
import { getQuorumPublicKey } from '../utils/getQuorumPublicKey';
|
|
4
|
+
import bytesToHex from '../utils/bytesToHex';
|
|
5
|
+
import verifyTenderdashProof from '../utils/verifyTenderdashProof';
|
|
6
|
+
export default async function getIdentityTokensBalances(grpcPool, identifier, tokenIdentifiers) {
|
|
7
|
+
const id = new IdentifierWASM(identifier);
|
|
8
|
+
const tokenIds = tokenIdentifiers.map(tokenIdentifier => new IdentifierWASM(tokenIdentifier));
|
|
9
|
+
const getIdentityTokenBalancesRequest = GetIdentityTokenBalancesRequest.create({
|
|
10
|
+
version: {
|
|
11
|
+
oneofKind: 'v0',
|
|
12
|
+
v0: {
|
|
13
|
+
tokenIds: tokenIds.map((identifier) => identifier.bytes()),
|
|
14
|
+
identityId: id.bytes(),
|
|
15
|
+
prove: true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const { response } = await grpcPool.getClient().getIdentityTokenBalances(getIdentityTokenBalancesRequest);
|
|
20
|
+
const { version } = response;
|
|
21
|
+
if (version.oneofKind !== 'v0') {
|
|
22
|
+
throw new Error('Unexpected oneOf type returned from DAPI (must be v0)');
|
|
23
|
+
}
|
|
24
|
+
const { v0 } = version;
|
|
25
|
+
if (v0.result.oneofKind !== 'proof') {
|
|
26
|
+
throw new Error('Unexpected oneOf type returned from DAPI (must be proof)');
|
|
27
|
+
}
|
|
28
|
+
const { result: { proof }, metadata } = v0;
|
|
29
|
+
if (metadata == null) {
|
|
30
|
+
throw new Error('Metadata not found');
|
|
31
|
+
}
|
|
32
|
+
const { rootHash, balances } = verifyTokensBalancesForIdentityProof(proof.grovedbProof, tokenIds, id, true, PlatformVersionWASM.PLATFORM_V9);
|
|
33
|
+
const quorumPublicKey = await getQuorumPublicKey(grpcPool.network, proof.quorumType, bytesToHex(proof.quorumHash));
|
|
34
|
+
const verify = await verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey);
|
|
35
|
+
if (!verify) {
|
|
36
|
+
throw new Error('Failed to verify query');
|
|
37
|
+
}
|
|
38
|
+
return balances
|
|
39
|
+
.map((tokenBalance) => ({
|
|
40
|
+
tokenId: new IdentifierWASM(tokenBalance.tokenId),
|
|
41
|
+
balance: tokenBalance.balance
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { GetTokenContractInfoRequest } from '../../proto/generated/platform';
|
|
2
|
+
import { IdentifierWASM, PlatformVersionWASM, verifyTokenContractInfoProof } from 'pshenmic-dpp';
|
|
3
|
+
import { getQuorumPublicKey } from '../utils/getQuorumPublicKey';
|
|
4
|
+
import bytesToHex from '../utils/bytesToHex';
|
|
5
|
+
import verifyTenderdashProof from '../utils/verifyTenderdashProof';
|
|
6
|
+
export default async function getTokenContractInfo(grpcPool, tokenIdentifier) {
|
|
7
|
+
const tokenId = new IdentifierWASM(tokenIdentifier);
|
|
8
|
+
const getTokenContractInfoRequest = GetTokenContractInfoRequest.create({
|
|
9
|
+
version: {
|
|
10
|
+
oneofKind: 'v0',
|
|
11
|
+
v0: {
|
|
12
|
+
tokenId: (tokenId).bytes(),
|
|
13
|
+
prove: true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
const { response } = await grpcPool.getClient().getTokenContractInfo(getTokenContractInfoRequest);
|
|
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, contractInfo } = verifyTokenContractInfoProof(proof.grovedbProof, tokenId, true, PlatformVersionWASM.PLATFORM_V9);
|
|
31
|
+
if (contractInfo == null) {
|
|
32
|
+
throw new Error('ContractInfo not found');
|
|
33
|
+
}
|
|
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 {
|
|
40
|
+
dataContractId: contractInfo.contractId,
|
|
41
|
+
tokenContractPosition: contractInfo.tokenContractPosition
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { IdentifierWASM, PlatformVersionWASM, verifyTokenDirectPurchasePrices } from 'pshenmic-dpp';
|
|
2
|
+
import { getQuorumPublicKey } from '../utils/getQuorumPublicKey';
|
|
3
|
+
import verifyTenderdashProof from '../utils/verifyTenderdashProof';
|
|
4
|
+
import bytesToHex from '../utils/bytesToHex';
|
|
5
|
+
import { GetTokenDirectPurchasePricesRequest } from '../../proto/generated/platform';
|
|
6
|
+
export default async function getTokenDirectPurchasePrices(grpcPool, tokenIdentifiers) {
|
|
7
|
+
const tokenIds = tokenIdentifiers.map(tokenId => new IdentifierWASM(tokenId).bytes());
|
|
8
|
+
const request = GetTokenDirectPurchasePricesRequest.create({
|
|
9
|
+
version: {
|
|
10
|
+
oneofKind: 'v0',
|
|
11
|
+
v0: {
|
|
12
|
+
tokenIds,
|
|
13
|
+
prove: true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
const { response } = await grpcPool.getClient().getTokenDirectPurchasePrices(request);
|
|
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, prices } = verifyTokenDirectPurchasePrices(proof.grovedbProof, tokenIds, true, PlatformVersionWASM.PLATFORM_V9);
|
|
31
|
+
if (prices == null) {
|
|
32
|
+
throw new Error('Prices not found');
|
|
33
|
+
}
|
|
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 prices;
|
|
40
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GetTokenTotalSupplyRequest } from '../../proto/generated/platform';
|
|
2
|
+
import { IdentifierWASM, PlatformVersionWASM, verifyTokenTotalSupplyProof } from 'pshenmic-dpp';
|
|
3
|
+
import { getQuorumPublicKey } from '../utils/getQuorumPublicKey';
|
|
4
|
+
import bytesToHex from '../utils/bytesToHex';
|
|
5
|
+
import verifyTenderdashProof from '../utils/verifyTenderdashProof';
|
|
6
|
+
export default async function getTokenTotalSupply(grpcPool, tokenIdentifier) {
|
|
7
|
+
const tokenId = new IdentifierWASM(tokenIdentifier);
|
|
8
|
+
const getTokenTotalSupplyRequest = GetTokenTotalSupplyRequest.create({
|
|
9
|
+
version: {
|
|
10
|
+
oneofKind: 'v0',
|
|
11
|
+
v0: {
|
|
12
|
+
tokenId: (tokenId).bytes(),
|
|
13
|
+
prove: true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
const { response } = await grpcPool.getClient().getTokenTotalSupply(getTokenTotalSupplyRequest);
|
|
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, totalBalance } = verifyTokenTotalSupplyProof(proof.grovedbProof, tokenId, true, PlatformVersionWASM.PLATFORM_V9);
|
|
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 {
|
|
37
|
+
tokenId,
|
|
38
|
+
totalSystemAmount: totalBalance.tokenSupply,
|
|
39
|
+
totalAggregatedAmountInUserAccounts: totalBalance.aggregatedTokenAccountBalances
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import getIdentitiesTokenBalances from './getIdentitiesTokenBalances';
|
|
2
|
+
import getIdentityTokensBalances from './getIdentityTokensBalances';
|
|
3
|
+
import getTokenContractInfo from './getTokenContractInfo';
|
|
4
|
+
import getTokenTotalSupply from './getTokenTotalSupply';
|
|
5
|
+
import createStateTransition from './createStateTransition';
|
|
6
|
+
import { IdentifierWASM, TokenBaseTransitionWASM, TokenPricingScheduleWASM } from 'pshenmic-dpp';
|
|
7
|
+
import getIdentityContractNonce from '../identities/getIdentityContractNonce';
|
|
8
|
+
import getTokenDirectPurchasePrices from './getTokenDirectPurchasePrices';
|
|
9
|
+
/**
|
|
10
|
+
* Tokens controller for requesting information about tokens and tokens holders
|
|
11
|
+
*
|
|
12
|
+
* @hideconstructor
|
|
13
|
+
*/
|
|
14
|
+
export class TokensController {
|
|
15
|
+
/** @ignore **/
|
|
16
|
+
grpcPool;
|
|
17
|
+
constructor(grpcPool) {
|
|
18
|
+
this.grpcPool = grpcPool;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves a token balances for identities
|
|
22
|
+
*
|
|
23
|
+
* @param identifiers {IdentifierLike[]} - list of identifiers which balance we need to get
|
|
24
|
+
* @param tokenIdentifier {IdentifierLike} - token identifier
|
|
25
|
+
*
|
|
26
|
+
* @return {Promise<IdentitiesTokenBalances>}
|
|
27
|
+
*/
|
|
28
|
+
async getIdentitiesTokenBalances(identifiers, tokenIdentifier) {
|
|
29
|
+
return await getIdentitiesTokenBalances(this.grpcPool, identifiers, tokenIdentifier);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Retrieves a tokens balances for identity
|
|
33
|
+
*
|
|
34
|
+
* @param identifier {IdentifierLike} - identifier which balance we need to get
|
|
35
|
+
* @param tokenIdentifiers {IdentifierLike[]} - list of tokens ids which used in request
|
|
36
|
+
*
|
|
37
|
+
* @return {Promise<IdentityTokenBalances>}
|
|
38
|
+
*/
|
|
39
|
+
async getIdentityTokensBalances(identifier, tokenIdentifiers) {
|
|
40
|
+
return await getIdentityTokensBalances(this.grpcPool, identifier, tokenIdentifiers);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Retrieves a tokens contract info by id
|
|
44
|
+
*
|
|
45
|
+
* @param tokenIdentifier {IdentifierLike} - token id which contract info we need
|
|
46
|
+
*
|
|
47
|
+
* @return {Promise<TokenContractInfo>}
|
|
48
|
+
*/
|
|
49
|
+
async getTokenContractInfo(tokenIdentifier) {
|
|
50
|
+
return await getTokenContractInfo(this.grpcPool, tokenIdentifier);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Retrieves a token total supply
|
|
54
|
+
*
|
|
55
|
+
* @param tokenIdentifier {IdentifierLike} - token id which total supply we need
|
|
56
|
+
*
|
|
57
|
+
* @return {Promise<TokenTotalSupply>}
|
|
58
|
+
*/
|
|
59
|
+
async getTokenTotalSupply(tokenIdentifier) {
|
|
60
|
+
return await getTokenTotalSupply(this.grpcPool, tokenIdentifier);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Retrieves a tokens prices
|
|
64
|
+
*
|
|
65
|
+
* @param tokenIdentifiers {IdentifierLike[]} - token ids which price we need
|
|
66
|
+
*
|
|
67
|
+
* @return {Promise<TokenDirectPurchasePrices[]>}
|
|
68
|
+
*/
|
|
69
|
+
async getTokensDirectPurchasePrice(tokenIdentifiers) {
|
|
70
|
+
return await getTokenDirectPurchasePrices(this.grpcPool, tokenIdentifiers);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Creates a Token Base Transition that contains base information about token transition
|
|
74
|
+
*
|
|
75
|
+
* @param tokenId {IdentifierLike} - token identifier
|
|
76
|
+
* @param ownerId {IdentifierLike} - identity identifier of sender of the transaction
|
|
77
|
+
*
|
|
78
|
+
* @return {TokenBaseTransitionWASM}
|
|
79
|
+
*/
|
|
80
|
+
async createBaseTransition(tokenId, ownerId) {
|
|
81
|
+
const { dataContractId, tokenContractPosition } = await getTokenContractInfo(this.grpcPool, tokenId);
|
|
82
|
+
const identityContractNonce = await getIdentityContractNonce(this.grpcPool, ownerId, dataContractId);
|
|
83
|
+
return new TokenBaseTransitionWASM(identityContractNonce + BigInt(1), tokenContractPosition, dataContractId, tokenId, undefined);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Helper function for creation of a token state transition to be broadcasted in the network
|
|
87
|
+
*
|
|
88
|
+
* You have to pass token base transition acquired from .createBaseTransition() method
|
|
89
|
+
* together with token transition type and its params
|
|
90
|
+
*
|
|
91
|
+
* @param base {TokenBaseTransitionWASM} - token Base transition
|
|
92
|
+
* @param ownerId {IdentifierLike} - `identity identifier of the owner of the transaction`
|
|
93
|
+
* @param type {TokenTransitionType} - token transition type as string (f.e. 'transfer')
|
|
94
|
+
* @param params {TokenTransitionParams} - params required for a token transition
|
|
95
|
+
*
|
|
96
|
+
* @return {StateTransitionWASM}
|
|
97
|
+
*/
|
|
98
|
+
createStateTransition(base, ownerId, type, params) {
|
|
99
|
+
const owner = new IdentifierWASM(ownerId);
|
|
100
|
+
if (params.identityId != null) {
|
|
101
|
+
params.identityId = new IdentifierWASM(params.identityId);
|
|
102
|
+
}
|
|
103
|
+
if (params.price != null && typeof params.price === 'bigint') {
|
|
104
|
+
params.price = TokenPricingScheduleWASM.SinglePrice(params.price);
|
|
105
|
+
}
|
|
106
|
+
return createStateTransition(base, owner, type, params);
|
|
107
|
+
}
|
|
108
|
+
}
|
package/src/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { IdentifierWASM, IdentityWASM, DocumentWASM, DataContractWASM, StateTransitionWASM, IdentityPublicKeyWASM } from 'pshenmic-dpp';
|
|
2
|
+
export { DashPlatformSDK } from './DashPlatformSDK';
|
|
3
|
+
export var ContestedStateResultType;
|
|
4
|
+
(function (ContestedStateResultType) {
|
|
5
|
+
ContestedStateResultType[ContestedStateResultType["DOCUMENTS"] = 0] = "DOCUMENTS";
|
|
6
|
+
ContestedStateResultType[ContestedStateResultType["VOTE_TALLY"] = 1] = "VOTE_TALLY";
|
|
7
|
+
ContestedStateResultType[ContestedStateResultType["DOCUMENTS_AND_VOTE_TALLY"] = 2] = "DOCUMENTS_AND_VOTE_TALLY";
|
|
8
|
+
})(ContestedStateResultType || (ContestedStateResultType = {}));
|
|
9
|
+
export var FinishedVoteOutcome;
|
|
10
|
+
(function (FinishedVoteOutcome) {
|
|
11
|
+
FinishedVoteOutcome[FinishedVoteOutcome["TOWARDS_IDENTITY"] = 0] = "TOWARDS_IDENTITY";
|
|
12
|
+
FinishedVoteOutcome[FinishedVoteOutcome["LOCKED"] = 1] = "LOCKED";
|
|
13
|
+
FinishedVoteOutcome[FinishedVoteOutcome["NO_PREVIOUS_WINNER"] = 2] = "NO_PREVIOUS_WINNER";
|
|
14
|
+
FinishedVoteOutcome[FinishedVoteOutcome["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
|
15
|
+
})(FinishedVoteOutcome || (FinishedVoteOutcome = {}));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import sha256 from './sha256';
|
|
2
|
+
export async function calculateMsgHash(chainId, height, round, type, blockId, stateId) {
|
|
3
|
+
const fixedSize = 4 + 8 + 8 + 32 + 32;
|
|
4
|
+
const chainIdBytes = new TextEncoder().encode(chainId);
|
|
5
|
+
const totalSize = fixedSize + chainIdBytes.length;
|
|
6
|
+
const buffer = new ArrayBuffer(totalSize);
|
|
7
|
+
const view = new DataView(buffer);
|
|
8
|
+
const uint8View = new Uint8Array(buffer);
|
|
9
|
+
let offset = 0;
|
|
10
|
+
// Write type as 32-bit little-endian integer
|
|
11
|
+
view.setInt32(offset, type, true);
|
|
12
|
+
offset += 4;
|
|
13
|
+
// Write height as 64-bit little-endian integer
|
|
14
|
+
view.setBigUint64(offset, height, true);
|
|
15
|
+
offset += 8;
|
|
16
|
+
// Write round as 64-bit little-endian integer
|
|
17
|
+
view.setBigUint64(offset, BigInt(round), true);
|
|
18
|
+
offset += 8;
|
|
19
|
+
// Copy blockId (32 bytes)
|
|
20
|
+
uint8View.set(blockId, offset);
|
|
21
|
+
offset += 32;
|
|
22
|
+
// Copy stateId (32 bytes)
|
|
23
|
+
uint8View.set(stateId, offset);
|
|
24
|
+
offset += 32;
|
|
25
|
+
if (offset !== fixedSize) {
|
|
26
|
+
throw new Error('Invalid input length while encoding sign bytes');
|
|
27
|
+
}
|
|
28
|
+
// Copy chainId bytes
|
|
29
|
+
uint8View.set(chainIdBytes, offset);
|
|
30
|
+
return await sha256(uint8View);
|
|
31
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { calculateMsgHash } from './calculateMsgHash';
|
|
2
|
+
import signRequestId from './signRequestId';
|
|
3
|
+
import signHash from './signHash';
|
|
4
|
+
export async function calculateSignHash(commit, chainId, quorumType, quorumHash, height, round) {
|
|
5
|
+
const requestId = await signRequestId('dpbvote', height, round);
|
|
6
|
+
const signBytesHash = await calculateMsgHash(chainId, height, round, commit.type, commit.blockId, commit.stateId);
|
|
7
|
+
return await signHash(quorumType, quorumHash, requestId, signBytesHash);
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { StateId } from '../../proto/generated/platform';
|
|
2
|
+
import sha256 from './sha256';
|
|
3
|
+
import { BinaryWriter } from '@bufbuild/protobuf/wire';
|
|
4
|
+
export async function calculateStateIdHash(stateId) {
|
|
5
|
+
const writer = new BinaryWriter();
|
|
6
|
+
// @ts-expect-error
|
|
7
|
+
const encoded = StateId.internalBinaryWrite(stateId, writer, { writeUnknownFields: false }).finish();
|
|
8
|
+
writer.bytes(encoded);
|
|
9
|
+
return await sha256(writer.finish());
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IdentifierWASM } from 'pshenmic-dpp';
|
|
2
|
+
import sha256 from './sha256';
|
|
3
|
+
import bytesToHex from './bytesToHex';
|
|
4
|
+
import hexToBytes from './hexToBytes';
|
|
5
|
+
export async function createVoterIdentityId(proTxHash, publicKeyHash) {
|
|
6
|
+
const proTxHashBytes = hexToBytes(proTxHash);
|
|
7
|
+
const publicKeyHashBytes = hexToBytes(publicKeyHash);
|
|
8
|
+
const mergedArray = new Uint8Array(proTxHashBytes.length + publicKeyHashBytes.length);
|
|
9
|
+
mergedArray.set(proTxHashBytes);
|
|
10
|
+
mergedArray.set(publicKeyHashBytes, proTxHashBytes.length);
|
|
11
|
+
const voterIdentifierBytes = await sha256(mergedArray);
|
|
12
|
+
return IdentifierWASM.fromHex(bytesToHex(voterIdentifierBytes));
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default async function getDAPINodeList(network) {
|
|
2
|
+
const url = `https://${network === 'mainnet' ? '' : 'testnet.'}platform-explorer.pshenmic.dev/validators?isActive=true`;
|
|
3
|
+
const resp = await fetch(url);
|
|
4
|
+
if (resp.status !== 200) {
|
|
5
|
+
throw new Error('Failed to query Platform Explorer for active validators');
|
|
6
|
+
}
|
|
7
|
+
const { resultSet } = await resp.json();
|
|
8
|
+
return resultSet
|
|
9
|
+
// eslint-disable-next-line
|
|
10
|
+
.map((validator) => validator?.proTxInfo?.state?.service ? `https://${validator.proTxInfo.state.service.split(':')[0]}${network === 'mainnet' ? '' : ':1443'}` : undefined)
|
|
11
|
+
.filter(e => e != null);
|
|
12
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const cache = {};
|
|
2
|
+
export async function getQuorumPublicKey(network, quorumType, quorumHash) {
|
|
3
|
+
const cached = cache[`${quorumType}_${quorumHash}`];
|
|
4
|
+
if (cached != null) {
|
|
5
|
+
return cached;
|
|
6
|
+
}
|
|
7
|
+
const url = `https://${network === 'mainnet' ? '' : 'testnet.'}platform-explorer.pshenmic.dev/quorum/info?quorumType=${quorumType}&quorumHash=${quorumHash}`;
|
|
8
|
+
const resp = await fetch(url, {
|
|
9
|
+
method: 'GET'
|
|
10
|
+
});
|
|
11
|
+
if (resp.status !== 200) {
|
|
12
|
+
throw new Error('Failed to query Platform Explorer for quorum public keys');
|
|
13
|
+
}
|
|
14
|
+
const data = await resp.json();
|
|
15
|
+
const { quorumPublicKey } = data;
|
|
16
|
+
cache[`${quorumType}_${quorumHash}`] = quorumPublicKey;
|
|
17
|
+
return quorumPublicKey;
|
|
18
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import convertToHomographSafeChars from './convertToHomographSafeChars';
|
|
2
|
+
import { base58 } from '@scure/base';
|
|
3
|
+
import hexToBytes from './hexToBytes';
|
|
4
|
+
import bytesToHex from './bytesToHex';
|
|
5
|
+
/**
|
|
6
|
+
* Collection of conversion functions
|
|
7
|
+
*
|
|
8
|
+
* @hideconstructor
|
|
9
|
+
*/
|
|
10
|
+
export class UtilsController {
|
|
11
|
+
/**
|
|
12
|
+
* Converts base58 string to an Uint8Array
|
|
13
|
+
*
|
|
14
|
+
* @param str {string}
|
|
15
|
+
*
|
|
16
|
+
* @returns {Uint8Array}
|
|
17
|
+
*/
|
|
18
|
+
base58ToBytes(str) {
|
|
19
|
+
return base58.decode(str);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Converts Uint8Array to base58 string
|
|
23
|
+
*
|
|
24
|
+
* @param bytes {Uint8Array}
|
|
25
|
+
*
|
|
26
|
+
* @return {string}
|
|
27
|
+
*/
|
|
28
|
+
bytesToBase58(bytes) {
|
|
29
|
+
return base58.encode(bytes);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Converts Uint8Array to hex string
|
|
33
|
+
*
|
|
34
|
+
* @param bytes {Uint8Array}
|
|
35
|
+
*
|
|
36
|
+
* @return {string}
|
|
37
|
+
*/
|
|
38
|
+
bytesToHex(bytes) {
|
|
39
|
+
return bytesToHex(bytes);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Converts a hex string to Uint8Array
|
|
43
|
+
*
|
|
44
|
+
* @param hex {string} hex-encoded string
|
|
45
|
+
*
|
|
46
|
+
* @return {Uint8Array}
|
|
47
|
+
*/
|
|
48
|
+
hexToBytes(hex) {
|
|
49
|
+
return hexToBytes(hex);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @deprecated use sdk.names.normalizeLabel()
|
|
53
|
+
*
|
|
54
|
+
* @param str {string}
|
|
55
|
+
*
|
|
56
|
+
* @return {string}
|
|
57
|
+
*/
|
|
58
|
+
convertToHomographSafeChars(str) {
|
|
59
|
+
return convertToHomographSafeChars(str);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import bytesToHex from './bytesToHex';
|
|
2
|
+
import { typedArrayToBuffer } from './bytesToTypedArray';
|
|
3
|
+
export default async function sha256(input) {
|
|
4
|
+
if (typeof input === 'string') {
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
const data = encoder.encode(input);
|
|
7
|
+
const hash = await crypto.subtle.digest('SHA-256', data);
|
|
8
|
+
return bytesToHex(new Uint8Array(hash));
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
const arrayBuffer = typedArrayToBuffer(input);
|
|
12
|
+
const hash = await crypto.subtle.digest('SHA-256', arrayBuffer);
|
|
13
|
+
return new Uint8Array(hash);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import sha256 from './sha256';
|
|
2
|
+
export default async function signHash(quorumType, quorumHash, requestId, signBytesHash) {
|
|
3
|
+
// Calculate total length: 1 byte for quorumType + 3 arrays of 32 bytes each
|
|
4
|
+
const totalLength = 1 + quorumHash.length + requestId.length + signBytesHash.length;
|
|
5
|
+
const combined = new Uint8Array(totalLength);
|
|
6
|
+
let offset = 0;
|
|
7
|
+
// Add quorumType as single byte
|
|
8
|
+
combined[offset] = quorumType;
|
|
9
|
+
offset += 1;
|
|
10
|
+
// Add reversed quorumHash
|
|
11
|
+
const reversedQuorumHash = new Uint8Array(quorumHash).reverse();
|
|
12
|
+
combined.set(reversedQuorumHash, offset);
|
|
13
|
+
offset += quorumHash.length;
|
|
14
|
+
// Add reversed requestId
|
|
15
|
+
const reversedRequestId = new Uint8Array(requestId).reverse();
|
|
16
|
+
combined.set(reversedRequestId, offset);
|
|
17
|
+
offset += requestId.length;
|
|
18
|
+
// Add reversed signBytesHash
|
|
19
|
+
const reversedSignBytesHash = new Uint8Array(signBytesHash).reverse();
|
|
20
|
+
combined.set(reversedSignBytesHash, offset);
|
|
21
|
+
return await sha256(await sha256(combined));
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import sha256 from './sha256';
|
|
2
|
+
export default async function signRequestId(prefix, height, round) {
|
|
3
|
+
const prefixBytes = new TextEncoder().encode(prefix);
|
|
4
|
+
// len + i64 + i32 (prefix length + 8 bytes for height + 4 bytes for round)
|
|
5
|
+
const totalLength = prefixBytes.length + 8 + 4;
|
|
6
|
+
const buffer = new ArrayBuffer(totalLength);
|
|
7
|
+
const view = new DataView(buffer);
|
|
8
|
+
const uint8View = new Uint8Array(buffer);
|
|
9
|
+
let offset = 0;
|
|
10
|
+
// Copy prefix bytes
|
|
11
|
+
uint8View.set(prefixBytes, offset);
|
|
12
|
+
offset += prefixBytes.length;
|
|
13
|
+
// Write height as 64-bit little-endian integer
|
|
14
|
+
view.setBigUint64(offset, height, true);
|
|
15
|
+
offset += 8;
|
|
16
|
+
// Write round as 32-bit little-endian integer
|
|
17
|
+
view.setInt32(offset, round, true);
|
|
18
|
+
return await sha256(uint8View);
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default function stringToIndexValueBytes(name) {
|
|
2
|
+
const lengthBuffer = new Uint8Array(1);
|
|
3
|
+
lengthBuffer[0] = name.length;
|
|
4
|
+
const nameBuffer = new TextEncoder().encode(name);
|
|
5
|
+
const result = new Uint8Array(1 + 1 + nameBuffer.length);
|
|
6
|
+
result[0] = 0x12;
|
|
7
|
+
result[1] = lengthBuffer[0];
|
|
8
|
+
result.set(nameBuffer, 2);
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CanonicalVote, SignedMsgType, StateId } from '../../proto/generated/platform';
|
|
2
|
+
import { calculateSignHash } from './calculateSignHash';
|
|
3
|
+
import { calculateStateIdHash } from './calculateStateIdHash';
|
|
4
|
+
import { verifySignatureDigest } from 'pshenmic-dpp';
|
|
5
|
+
import hexToBytes from './hexToBytes';
|
|
6
|
+
export default async function verifyTenderdashProof(proof, metadata, rootHash, quorumPublicKey) {
|
|
7
|
+
const stateId = StateId.create({
|
|
8
|
+
appVersion: String(metadata.protocolVersion),
|
|
9
|
+
coreChainLockedHeight: metadata.coreChainLockedHeight,
|
|
10
|
+
time: metadata.timeMs,
|
|
11
|
+
appHash: rootHash,
|
|
12
|
+
height: metadata.height
|
|
13
|
+
});
|
|
14
|
+
const stateIdHash = await calculateStateIdHash(stateId);
|
|
15
|
+
const commit = CanonicalVote.create({
|
|
16
|
+
type: SignedMsgType.PRECOMMIT,
|
|
17
|
+
blockId: proof.blockIdHash,
|
|
18
|
+
chainId: metadata.chainId,
|
|
19
|
+
height: metadata.height,
|
|
20
|
+
round: String(proof.round),
|
|
21
|
+
stateId: stateIdHash
|
|
22
|
+
});
|
|
23
|
+
const signDigest = await calculateSignHash(commit, metadata.chainId, proof.quorumType, proof.quorumHash, BigInt(metadata.height), proof.round);
|
|
24
|
+
const { signature } = proof;
|
|
25
|
+
return verifySignatureDigest(Uint8Array.from(signDigest), signature, hexToBytes(quorumPublicKey));
|
|
26
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IdentifierWASM, MasternodeVoteTransitionWASM } from 'pshenmic-dpp';
|
|
2
|
+
export default function createStateTransition(voteWASM, proTxHash, identityNonce) {
|
|
3
|
+
const voterIdentity = IdentifierWASM.fromHex(proTxHash);
|
|
4
|
+
const masternodeVoteTransition = new MasternodeVoteTransitionWASM(proTxHash, voterIdentity, voteWASM, identityNonce);
|
|
5
|
+
return masternodeVoteTransition.toStateTransition();
|
|
6
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { VotePollWASM, VoteWASM } from 'pshenmic-dpp';
|
|
2
|
+
export default function createVote(dataContractId, documentTypeName, indexName, indexValues, choice) {
|
|
3
|
+
const votePoll = new VotePollWASM(dataContractId, documentTypeName, indexName, indexValues);
|
|
4
|
+
return new VoteWASM(votePoll, choice);
|
|
5
|
+
}
|