Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk): token and group queries #2449

Open
wants to merge 38 commits into
base: v2.0-tokens-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0d97d80
chore: implement proof verification sugar for new queries
shumkov Jan 28, 2025
474ecfa
chore: add methods for new queries to dapi client
shumkov Jan 28, 2025
f5d1f71
chore: fetch implementation in progress
shumkov Jan 29, 2025
ed9dc9e
chore(sdk): implement queries and fetch methods
shumkov Jan 29, 2025
a23f8d0
Merge branch 'v2.0-tokens-dev' into feat/sdk/queries
shumkov Jan 30, 2025
c2c3c94
fix: fetch implementation for non-optional values
shumkov Jan 30, 2025
9d4920d
fix: fetch objects aren't available from SDK
shumkov Feb 1, 2025
3e571e6
feat(drive): add generate test data logic for init chain
shumkov Feb 3, 2025
bdd7ff8
chore(sdk): improvements and fixes for token queries
shumkov Feb 3, 2025
22212aa
test(sdk): fix SDK test framework
shumkov Feb 3, 2025
21de3a4
test(sdk): add query and group tests
shumkov Feb 3, 2025
27bf8bf
refactor: minor refactorings after PR review
shumkov Feb 3, 2025
9816146
refactor: remove broadcast methods from ST builders
shumkov Feb 3, 2025
42e3e16
fix: some minor fixes
shumkov Feb 3, 2025
1c3ba5e
fix: identity contract nonce
shumkov Feb 3, 2025
e56f057
test: fixtures
shumkov Feb 4, 2025
fdab153
test: more fixtures
shumkov Feb 4, 2025
2351b50
fix: proof result error for credit transfers in sdk
pauldelucia Feb 4, 2025
79f7038
fix: `TokenTransition` has no methods
shumkov Feb 4, 2025
da14f7c
chore: print identity keys
shumkov Feb 4, 2025
21c4d73
Merge remote-tracking branch 'origin/feat/sdk/queries' into feat/sdk/…
shumkov Feb 4, 2025
28727ac
fix: missing methods in token transitions
shumkov Feb 4, 2025
288dca1
chore: add getProof request logging
shumkov Feb 4, 2025
440fc27
fix: more missing methods
shumkov Feb 5, 2025
f173e89
test: fix tests
shumkov Feb 5, 2025
f445d52
fix: invalid GetProof request
shumkov Feb 5, 2025
a52b6bc
fix: cannot read properties of undefined (reading 'dataContract')
shumkov Feb 5, 2025
e317e47
fix: cannot read properties of undefined (reading 'toString')
shumkov Feb 6, 2025
a365cfd
fix: wrong data contract id to verify historical token proof
shumkov Feb 6, 2025
84359ea
fix: the token config is fetched wrong the wrong contract
shumkov Feb 6, 2025
bbadd12
fix: can't create a token contract from buffer
shumkov Feb 6, 2025
a0402cd
set limit to 1 on single key sized query
pauldelucia Feb 7, 2025
3e87933
fix: proofs for historical contracts
shumkov Feb 7, 2025
c809ebd
Merge remote-tracking branch 'origin/feat/sdk/queries' into feat/sdk/…
shumkov Feb 7, 2025
58259a3
fix: set limit to 1 for token info for id query
pauldelucia Feb 10, 2025
1e2b0b9
fix: invalid token contract id
shumkov Feb 11, 2025
d728f64
fix: token history contract description
pauldelucia Feb 11, 2025
4397cec
chore: update example token contract
pauldelucia Feb 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,7 @@ COPY --from=build-dapi /platform/packages/dapi /platform/packages/dapi
COPY --from=build-dapi /platform/packages/dapi-grpc /platform/packages/dapi-grpc
COPY --from=build-dapi /platform/packages/js-grpc-common /platform/packages/js-grpc-common
COPY --from=build-dapi /platform/packages/wasm-dpp /platform/packages/wasm-dpp
COPY --from=build-dapi /platform/packages/token-history-contract /platform/packages/token-history-contract

RUN cp /platform/packages/dapi/.env.example /platform/packages/dapi/.env

Expand Down
16 changes: 14 additions & 2 deletions packages/dapi-grpc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
// Derive features for versioned messages
//
// "GetConsensusParamsRequest" is excluded as this message does not support proofs
const VERSIONED_REQUESTS: [&str; 34] = [
const VERSIONED_REQUESTS: [&str; 40] = [
"GetDataContractHistoryRequest",
"GetDataContractRequest",
"GetDataContractsRequest",
Expand Down Expand Up @@ -82,14 +82,20 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
"GetIdentitiesTokenBalancesRequest",
"GetIdentityTokenInfosRequest",
"GetIdentitiesTokenInfosRequest",
"GetTokenStatusesRequest",
"GetTokenTotalSupplyRequest",
"GetGroupInfoRequest",
"GetGroupInfosRequest",
"GetGroupActionsRequest",
"GetGroupActionSignersRequest",
];

// The following responses are excluded as they don't support proofs:
// - "GetConsensusParamsResponse"
// - "GetStatusResponse"
//
// "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests
const VERSIONED_RESPONSES: [&str; 33] = [
const VERSIONED_RESPONSES: [&str; 39] = [
"GetDataContractHistoryResponse",
"GetDataContractResponse",
"GetDataContractsResponse",
Expand Down Expand Up @@ -123,6 +129,12 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
"GetIdentitiesTokenBalancesResponse",
"GetIdentityTokenInfosResponse",
"GetIdentitiesTokenInfosResponse",
"GetTokenStatusesResponse",
"GetTokenTotalSupplyResponse",
"GetGroupInfoResponse",
"GetGroupInfosResponse",
"GetGroupActionsResponse",
"GetGroupActionSignersResponse",
];

check_unique(&VERSIONED_REQUESTS).expect("VERSIONED_REQUESTS");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ const {
TokenTransitionType,
} = require('@dashevo/wasm-dpp');
const { GetDataContractRequest } = require('@dashevo/dapi-grpc/clients/platform/v0/web/platform_pb');
const { contractId: tokensHistoryContractIdString } = require('@dashevo/token-history-contract/lib/systemIds');
const bs58 = require('bs58');

/**
* @param {PlatformPromiseClient} driveClient
* @param {DashPlatformProtocol} dpp
* @return {fetchProofForStateTransition}
*/
function fetchProofForStateTransitionFactory(driveClient, dpp) {
const tokensHistoryContractIdBuffer = bs58.decode(tokensHistoryContractIdString);

/**
* @typedef {fetchProofForStateTransition}
* @param {AbstractStateTransition} stateTransition
Expand All @@ -30,7 +34,7 @@ function fetchProofForStateTransitionFactory(driveClient, dpp) {

const requestV0 = new GetProofsRequestV0();

let dataContractsCache = {};
const dataContractsCache = {};

if (stateTransition.isDocumentStateTransition()) {
const {
Expand All @@ -46,110 +50,117 @@ function fetchProofForStateTransitionFactory(driveClient, dpp) {
const tokenStatusesList = [];

for (const batchedTransition of stateTransition.getTransitions()) {
// Fetch data contract to determine correct recipient identity
const dataContractId = batchedTransition.getDataContractId();
const dataContractIdString = dataContractId.toString();

if (batchedTransition instanceof TokenTransition) {
switch (batchedTransition.getTransitionType()) {
case TokenTransitionType.Burn: {
const request = new IdentityTokenBalanceRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
identityId: stateTransition.getOwnerId()
.toBuffer(),
});

identityTokenBalancesList.push(request);
break;
}
case TokenTransitionType.Mint: {
// Fetch data contract to determine correct recipient identity
const dataContractId = batchedTransition.getDataContractId();
const dataContractIdString = dataContractId.toString();
if (!dataContractsCache[dataContractIdString]) {
const dataContractRequestV0 = new GetDataContractRequest.GetDataContractRequestV0();
dataContractRequestV0.setId(dataContractId.toBuffer());

if (!dataContractsCache[dataContractIdString]) {
const dataContractRequestV0 = new GetDataContractRequest.GetDataContractRequestV0({
id: dataContractId.toBuffer(),
});
const dataContractRequest = new GetDataContractRequest();
dataContractRequest.setV0(dataContractRequestV0);

const dataContractRequest = new GetDataContractRequest();
dataContractRequest.setV0(dataContractRequestV0);
const dataContractResponse = await driveClient.getDataContract(dataContractRequest);

const dataContractResponse = await driveClient.getDataContract(dataContractRequest);
const dataContractBuffer = Buffer.from(
dataContractResponse.getV0().getDataContract_asU8(),
);

dataContractsCache[dataContractIdString] = await dpp.dataContract
.createFromBuffer(dataContractBuffer, { skipValidation: true });
}

const dataContractBuffer = Buffer.from(
dataContractResponse.getV0().getDataContract_asU8(),
const dataContract = dataContractsCache[dataContractIdString];

const tokenConfiguration = dataContract.getTokenConfiguration(
batchedTransition.getTokenContractPosition(),
);

// In case if we keep history for token events we can provide better proof
// for clients
if (tokenConfiguration.keepsHistory()) {
const documentRequest = new DocumentRequest();
documentRequest.setContractId(tokensHistoryContractIdBuffer);
documentRequest.setDocumentType(batchedTransition.getHistoricalDocumentTypeName());

const documentId = batchedTransition.getHistoricalDocumentId(
stateTransition.getOwnerId(),
batchedTransition.getIdentityContractNonce(),
);

documentRequest.setDocumentId(documentId.toBuffer());

documentsList.push(documentRequest);
} else {
// If not we can provide only balance / supply proofs
switch (batchedTransition.getTransitionType()) {
case TokenTransitionType.Burn: {
const request = new IdentityTokenBalanceRequest();
request.setTokenId(batchedTransition.getTokenId().toBuffer());
request.setIdentityId(stateTransition.getOwnerId().toBuffer());

identityTokenBalancesList.push(request);
break;
}
case TokenTransitionType.Mint: {
const request = new IdentityTokenBalanceRequest();
request.setTokenId(batchedTransition.getTokenId().toBuffer());
request.setIdentityId(
batchedTransition.toTransition().getRecipientId(tokenConfiguration).toBuffer(),
);

dataContractsCache[dataContractIdString] = await dpp.dataContract
.createFromBuffer(dataContractBuffer);
identityTokenBalancesList.push(request);
break;
}
case TokenTransitionType.Transfer: {
const requestSender = new IdentityTokenBalanceRequest();
requestSender.setTokenId(batchedTransition.getTokenId().toBuffer());
requestSender.setIdentityId(stateTransition.getOwnerId().toBuffer());

const requestRecipient = new IdentityTokenBalanceRequest();
requestRecipient.setTokenId(batchedTransition.getTokenId().toBuffer());
requestRecipient.setIdentityId(
batchedTransition.toTransition().getRecipientId().toBuffer(),
);

const dataContract = dataContractsCache[dataContractIdString];
identityTokenBalancesList.push(requestSender, requestRecipient);
break;
}
case TokenTransitionType.DestroyFrozenFunds: {
const request = new IdentityTokenBalanceRequest();
request.setTokenId(batchedTransition.getTokenId().toBuffer());
request.setIdentityId(
batchedTransition.toTransition().getFrozenIdentityId().toBuffer(),
);

const tokenConfiguration = dataContract.getTokenConfiguration(
batchedTransition.getTokenContractPosition(),
);
identityTokenBalancesList.push(request);
break;
}
case TokenTransitionType.EmergencyAction:
{
const request = new TokenStatusRequest();

const request = new IdentityTokenBalanceRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
identityId: batchedTransition.toTransition().getRecipientId(tokenConfiguration)
.toBuffer(),
});
request.setTokenId(batchedTransition.getTokenId().toBuffer());

identityTokenBalancesList.push(request);
break;
}
case TokenTransitionType.Transfer: {
const requestSender = new IdentityTokenBalanceRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
identityId: stateTransition.getOwnerId().toBuffer(),
});

const requestRecipient = new IdentityTokenBalanceRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
identityId: batchedTransition.toTransition().getRecipientId()
.toBuffer(),
});

identityTokenBalancesList.push(requestSender, requestRecipient);
break;
}
case TokenTransitionType.DestroyFrozenFunds: {
const request = new IdentityTokenBalanceRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
identityId: batchedTransition.toTransition().getFrozenIdentityId()
.toBuffer(),
});

identityTokenBalancesList.push(request);
break;
}
case TokenTransitionType.EmergencyAction:
{
const request = new TokenStatusRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
});

tokenStatusesList.push(request);
break;
}
case TokenTransitionType.Freeze:
case TokenTransitionType.Unfreeze: {
const request = new IdentityTokenInfoRequest({
tokenId: batchedTransition.getTokenId()
.toBuffer(),
identityId: batchedTransition.toTransition().getFrozenIdentityId()
.toBuffer(),
});

identityTokenInfosList.push(request);
break;
tokenStatusesList.push(request);
break;
}
case TokenTransitionType.Freeze:
case TokenTransitionType.Unfreeze: {
const request = new IdentityTokenInfoRequest();
request.setTokenId(batchedTransition.getTokenId().toBuffer());
request.setIdentityId(
batchedTransition.toTransition().getFrozenIdentityId().toBuffer(),
);

identityTokenInfosList.push(request);
break;
}
default:
throw new Error(`Unsupported token transition type ${batchedTransition.getTransitionType()}`);
}
default:
throw new Error(`Unsupported token transition type ${batchedTransition.getTransitionType()}`);
}
} else if (batchedTransition instanceof DocumentTransition) {
const documentRequest = new DocumentRequest();
Expand Down Expand Up @@ -254,6 +265,9 @@ function fetchProofForStateTransitionFactory(driveClient, dpp) {
const request = new GetProofsRequest();
request.setV0(requestV0);

// TODO: Remove logging
console.dir(request.toObject(), { depth: null });

return driveClient.getProofs(request);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ function platformHandlersFactory(
);

// waitForStateTransitionResult
const fetchProofForStateTransition = fetchProofForStateTransitionFactory(driveClient);
const fetchProofForStateTransition = fetchProofForStateTransitionFactory(driveClient, dpp);

const getExistingTransactionResult = getExistingTransactionResultFactory(
rpcClient,
Expand Down
1 change: 1 addition & 0 deletions packages/dapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@dashevo/dashcore-lib": "~0.22.0",
"@dashevo/dashd-rpc": "^19.0.0",
"@dashevo/grpc-common": "workspace:*",
"@dashevo/token-history-contract": "workspace:*",
"@dashevo/wasm-dpp": "workspace:*",
"@grpc/grpc-js": "1.4.4",
"@pshenmic/zeromq": "6.0.0-beta.22",
Expand Down
2 changes: 1 addition & 1 deletion packages/dapi/scripts/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ async function main() {
});
logger.info(`JSON RPC server is listening on port ${config.rpcServer.port}`);

const dpp = new DashPlatformProtocol(null, 1);
const dpp = new DashPlatformProtocol(null, 9);

// Start GRPC server
logger.info('Starting GRPC server');
Expand Down
Loading