New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@concordium/node-sdk

Package Overview
Dependencies
Maintainers
4
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@concordium/node-sdk - npm Package Compare versions

Comparing version

to
1.1.0

9

CHANGELOG.md
# Changelog
## 1.1.0 2022-06-14
### Added
- Support for the Invoke contract node entrypoint.
### Fixed
- Lossy parsing of uint64's from the node, if their value was above MAX_SAFE_INTEGER.
## 1.0.0 2022-05-11

@@ -5,0 +14,0 @@

1

lib/pkg/package.json

@@ -10,3 +10,2 @@ {

"node_sdk_helpers.js",
"node_sdk_helpers_bg.js",
"node_sdk_helpers.d.ts"

@@ -13,0 +12,0 @@ ],

@@ -916,2 +916,42 @@ # concordium-node-sdk-js

## InvokeContract
Used to simulate a contract update, and to trigger view functions.
```js
const blockHash = "7f7409679e53875567e2ae812c9fcefe90ced8961d08554756f42bf268a42749";
const contractAddress = { index: 1n, subindex: 0n };
const invoker = new AccountAddress('3tXiu8d4CWeuC12irAB7YVb1hzp3YxsmmmNzzkdujCPqQ9EjDm');
const result = await client.invokeContract(
blockHash,
{
invoker: invoker,
contract: contractAddress,
method: 'PiggyBank.smash',
amount: undefined,
parameter: undefined,
energy: 30000n,
}
);
if (!result) {
// The node could not attempt the invocation, most likely the contract doesn't exist.
}
if (result.tag === 'failure') {
// Invoke was unsuccesful
const rejectReason = result.reason; // Describes why the update failed;
...
} else {
const events = result.events; // a list of events that would be generated by the update
const returnValue = result.returnValue; // If the invoked method has return value
...
}
```
Note that some of the parts of the context are optional:
- amount: defaults to 0
- energy: defaults to 10 million
- parameter: defaults to no parameters
- invoker: uses the zero account address, which can be used instead of finding a random address.
## Deserialize contract state

@@ -918,0 +958,0 @@ The following example demonstrates how to deserialize a contract's state:

@@ -6,3 +6,3 @@ import { ChannelCredentials, Metadata } from '@grpc/grpc-js';

import { PeerListResponse } from '../grpc/concordium_p2p_rpc_pb';
import { AccountInfo, AccountTransaction, AccountTransactionSignature, ArInfo, BlockInfo, BlockSummary, ConsensusStatus, ContractAddress, CredentialDeploymentTransaction, CryptographicParameters, IpInfo, NextAccountNonce, TransactionStatus, Versioned, InstanceInfo, BakerId, PoolStatus, BakerPoolStatus, RewardStatus, PassiveDelegationStatus } from './types';
import { AccountInfo, AccountTransaction, AccountTransactionSignature, ArInfo, BlockInfo, BlockSummary, ConsensusStatus, ContractAddress, CredentialDeploymentTransaction, CryptographicParameters, IpInfo, NextAccountNonce, TransactionStatus, Versioned, InstanceInfo, BakerId, PoolStatus, BakerPoolStatus, RewardStatus, PassiveDelegationStatus, ContractContext, InvokeContractResult } from './types';
import { ModuleReference } from './types/moduleReference';

@@ -171,3 +171,16 @@ /**

getModuleSource(blockHash: string, moduleReference: ModuleReference): Promise<Uint8Array>;
/**
* Invokes a smart contract.
* @param blockHash the block hash at which the contract should be invoked at. The contract is invoked in the state at the end of this block.
* @param context the collection of details used to invoke the contract. Must include the address of the contract and the method invoked.
* @returns If the node was able to invoke, then a object describing the outcome is returned.
* The outcome is determined by the `tag` field, which is either `success` or `failure`.
* The `usedEnergy` field will always be present, and is the amount of NRG was used during the execution.
* If the tag is `success`, then an `events` field is present, and it contains the events that would have been generated.
* If invoking a V1 contract and it produces a return value, it will be present in the `returnValue` field.
* If the tag is `failure`, then a `reason` field is present, and it contains the reason the update would have been rejected.
* If either the block does not exist, or then node fails to parse of any of the inputs, then undefined is returned.
*/
invokeContract(blockHash: string, contractContext: ContractContext): Promise<InvokeContractResult | undefined>;
sendRequest<T>(command: any, input: T): Promise<Uint8Array>;
}

@@ -439,2 +439,58 @@ "use strict";

}
/**
* Invokes a smart contract.
* @param blockHash the block hash at which the contract should be invoked at. The contract is invoked in the state at the end of this block.
* @param context the collection of details used to invoke the contract. Must include the address of the contract and the method invoked.
* @returns If the node was able to invoke, then a object describing the outcome is returned.
* The outcome is determined by the `tag` field, which is either `success` or `failure`.
* The `usedEnergy` field will always be present, and is the amount of NRG was used during the execution.
* If the tag is `success`, then an `events` field is present, and it contains the events that would have been generated.
* If invoking a V1 contract and it produces a return value, it will be present in the `returnValue` field.
* If the tag is `failure`, then a `reason` field is present, and it contains the reason the update would have been rejected.
* If either the block does not exist, or then node fails to parse of any of the inputs, then undefined is returned.
*/
async invokeContract(blockHash, contractContext) {
if (!(0, util_1.isValidHash)(blockHash)) {
throw new Error('The input was not a valid hash: ' + blockHash);
}
let invoker;
if (!contractContext.invoker) {
invoker = null;
}
else if (contractContext.invoker.address) {
invoker = {
type: 'AddressAccount',
address: contractContext.invoker.address,
};
}
else {
const invokerContract = contractContext.invoker;
invoker = {
type: 'AddressContract',
address: {
subindex: invokerContract.subindex.toString(),
index: invokerContract.index.toString(),
},
};
}
const requestObject = new concordium_p2p_rpc_pb_1.InvokeContractRequest();
requestObject.setBlockHash(blockHash);
requestObject.setContext((0, util_1.stringToInt)(JSON.stringify({
invoker,
contract: {
subindex: contractContext.contract.subindex.toString(),
index: contractContext.contract.index.toString(),
},
amount: contractContext.amount &&
contractContext.amount.microGtuAmount.toString(),
method: contractContext.method,
parameter: contractContext.parameter &&
contractContext.parameter.toString('hex'),
energy: contractContext.energy &&
Number(contractContext.energy.toString()),
}), ['index', 'subindex']));
const response = await this.sendRequest(this.client.invokeContract, requestObject);
const bigIntPropertyKeys = ['usedEnergy', 'index', 'subindex'];
return (0, util_1.unwrapJsonResponse)(response, (0, util_1.buildJsonResponseReviver)([], bigIntPropertyKeys), (0, util_1.intToStringTransformer)(bigIntPropertyKeys));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types

@@ -441,0 +497,0 @@ sendRequest(command, input) {

@@ -46,3 +46,3 @@ import { AccountAddress } from './types/accountAddress';

export interface TransactionEvent {
tag: 'ModuleDeployed' | 'ContractInitialized' | 'AccountCreated' | 'CredentialDeployed' | 'BakerAdded' | 'BakerRemoved' | 'BakerStakeIncreased' | 'BakerStakeDecreased' | 'BakerSetRestakeEarnings' | 'BakerKeysUpdated' | 'CredentialKeysUpdated' | 'NewEncryptedAmount' | 'EncryptedAmountsRemoved' | 'AmountAddedByDecryption' | 'EncryptedSelfAmountAdded' | 'UpdateEnqueued' | 'TransferredWithSchedule' | 'CredentialsUpdated' | 'DataRegistered' | 'Interrupted' | 'Resumed' | 'BakerSetOpenStatus' | 'BakerSetMetadataURL' | 'BakerSetTransactionFeeCommission' | 'BakerSetBakingRewardCommission' | 'BakerSetFinalizationRewardCommission' | 'DelegationStakeIncreased' | 'DelegationStakeDecreased' | 'DelegationSetRestakeEarnings' | 'DelegationSetDelegationTarget' | 'DelegationAdded' | 'DelegationRemoved';
tag: 'ModuleDeployed' | 'ContractInitialized' | 'AccountCreated' | 'CredentialDeployed' | 'BakerAdded' | 'BakerRemoved' | 'BakerStakeIncreased' | 'BakerStakeDecreased' | 'BakerSetRestakeEarnings' | 'BakerKeysUpdated' | 'CredentialKeysUpdated' | 'NewEncryptedAmount' | 'EncryptedAmountsRemoved' | 'AmountAddedByDecryption' | 'EncryptedSelfAmountAdded' | 'UpdateEnqueued' | 'TransferredWithSchedule' | 'CredentialsUpdated' | 'DataRegistered' | 'BakerSetOpenStatus' | 'BakerSetMetadataURL' | 'BakerSetTransactionFeeCommission' | 'BakerSetBakingRewardCommission' | 'BakerSetFinalizationRewardCommission' | 'DelegationStakeIncreased' | 'DelegationStakeDecreased' | 'DelegationSetRestakeEarnings' | 'DelegationSetDelegationTarget' | 'DelegationAdded' | 'DelegationRemoved';
}

@@ -53,2 +53,12 @@ export interface ContractAddress {

}
export interface InterruptedEvent {
tag: 'Interrupted';
address: ContractAddress;
events: string[];
}
export interface ResumedEvent {
tag: 'Resumed';
address: ContractAddress;
success: boolean;
}
export interface UpdatedEvent {

@@ -143,6 +153,22 @@ tag: 'Updated';

}
export interface RejectReason {
tag: RejectReasonTag;
export interface RejectedReceive {
tag: RejectReasonTag.RejectedReceive;
contractAddress: ContractAddress;
receiveName: string;
rejectReason: number;
parameter: string;
}
export interface RejectedInit {
tag: RejectReasonTag.RejectedInit;
rejectReason: number;
}
export declare type SimpleRejectReasonTag = RejectReasonTag.ModuleNotWF | RejectReasonTag.RuntimeFailure | RejectReasonTag.SerializationFailure | RejectReasonTag.OutOfEnergy | RejectReasonTag.InvalidProof | RejectReasonTag.InsufficientBalanceForBakerStake | RejectReasonTag.StakeUnderMinimumThresholdForBaking | RejectReasonTag.BakerInCooldown | RejectReasonTag.NonExistentCredentialID | RejectReasonTag.KeyIndexAlreadyInUse | RejectReasonTag.InvalidAccountThreshold | RejectReasonTag.InvalidCredentialKeySignThreshold | RejectReasonTag.InvalidEncryptedAmountTransferProof | RejectReasonTag.InvalidTransferToPublicProof | RejectReasonTag.InvalidIndexOnEncryptedTransfer | RejectReasonTag.ZeroScheduledAmount | RejectReasonTag.NonIncreasingSchedule | RejectReasonTag.FirstScheduledReleaseExpired | RejectReasonTag.InvalidCredentials | RejectReasonTag.RemoveFirstCredential | RejectReasonTag.CredentialHolderDidNotSign | RejectReasonTag.NotAllowedMultipleCredentials | RejectReasonTag.NotAllowedToReceiveEncrypted | RejectReasonTag.NotAllowedToHandleEncrypted | RejectReasonTag.MissingBakerAddParameters | RejectReasonTag.FinalizationRewardCommissionNotInRange | RejectReasonTag.BakingRewardCommissionNotInRange | RejectReasonTag.TransactionFeeCommissionNotInRange | RejectReasonTag.AlreadyADelegator | RejectReasonTag.InsufficientBalanceForDelegationStake | RejectReasonTag.MissingDelegationAddParameters | RejectReasonTag.InsufficientDelegationStake | RejectReasonTag.DelegatorInCooldown | RejectReasonTag.StakeOverMaximumThresholdForPool | RejectReasonTag.PoolWouldBecomeOverDelegated | RejectReasonTag.PoolClosed;
export interface SimpleRejectReason {
tag: SimpleRejectReasonTag;
}
export interface RejectReasonWithContents {
tag: Exclude<RejectReasonTag, RejectReasonTag.RejectedReceive | RejectReasonTag.RejectedInit | SimpleRejectReasonTag>;
contents: any;
}
export declare type RejectReason = RejectReasonWithContents | SimpleRejectReason | RejectedReceive | RejectedInit;
interface RejectedEventResult {

@@ -154,3 +180,3 @@ outcome: 'reject';

outcome: 'success';
events: (TransactionEvent | TransferredEvent | UpdatedEvent | MemoEvent | TransferredWithScheduleEvent)[];
events: (TransactionEvent | TransferredEvent | UpdatedEvent | ResumedEvent | InterruptedEvent | MemoEvent | TransferredWithScheduleEvent)[];
}

@@ -978,2 +1004,21 @@ export declare type EventResult = SuccessfulEventResult | TransferWithMemoEventResult | RejectedEventResult;

export declare type InstanceInfoSerialized = InstanceInfoSerializedV0 | InstanceInfoSerializedV1;
export interface ContractContext {
invoker?: ContractAddress | AccountAddress;
contract: ContractAddress;
amount?: GtuAmount;
method: string;
parameter?: Buffer;
energy?: bigint;
}
export interface InvokeContractSuccessResult extends Pick<SuccessfulEventResult, 'events'> {
tag: 'success';
usedEnergy: bigint;
returnValue?: string;
}
export interface InvokeContractFailedResult {
tag: 'failure';
usedEnergy: bigint;
reason: RejectReason;
}
export declare type InvokeContractResult = InvokeContractSuccessResult | InvokeContractFailedResult;
export interface CredentialDeploymentTransaction {

@@ -980,0 +1025,0 @@ expiry: TransactionExpiry;

import { AccountTransactionSignature } from './types';
export declare function intListToStringList(jsonStruct: string): string;
/**
* Replaces a string in a JSON string with the same string as a
* number, i.e. removing quotes (") prior to and after the string. This
* is needed as the default JSON stringify cannot serialize BigInts as numbers.
* So one can turn them into strings, stringify the structure, and then use this function
* to make those fields into JSON numbers.
* @param jsonStruct the JSON structure as a string
* @param keys the keys where the strings has to be unquoted
* @returns the same JSON string where the strings at the supplied keys are unquoted
*/
export declare function stringToInt(jsonStruct: string, keys: string[]): string;
/**
* A transformer that converts all the values provided as keys to

@@ -5,0 +16,0 @@ * string values.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.secondsSinceEpoch = exports.countSignatures = exports.isValidHash = exports.isHex = exports.buildJsonResponseReviver = exports.unwrapJsonResponse = exports.unwrapBoolResponse = exports.intToStringTransformer = exports.intListToStringList = void 0;
exports.secondsSinceEpoch = exports.countSignatures = exports.isValidHash = exports.isHex = exports.buildJsonResponseReviver = exports.unwrapJsonResponse = exports.unwrapBoolResponse = exports.intToStringTransformer = exports.stringToInt = exports.intListToStringList = void 0;
const concordium_p2p_rpc_pb_1 = require("../grpc/concordium_p2p_rpc_pb");

@@ -15,5 +15,5 @@ /**

function intToString(jsonStruct, keys) {
const result = jsonStruct;
let result = jsonStruct;
for (const key of keys) {
result.replace(new RegExp(`"${key}":\\s*([0-9]+)`, 'g'), `"${key}":"$1"`);
result = result.replace(new RegExp(`"${key}":\\s*([0-9]+)`, 'g'), `"${key}":"$1"`);
}

@@ -27,2 +27,20 @@ return result;

/**
* Replaces a string in a JSON string with the same string as a
* number, i.e. removing quotes (") prior to and after the string. This
* is needed as the default JSON stringify cannot serialize BigInts as numbers.
* So one can turn them into strings, stringify the structure, and then use this function
* to make those fields into JSON numbers.
* @param jsonStruct the JSON structure as a string
* @param keys the keys where the strings has to be unquoted
* @returns the same JSON string where the strings at the supplied keys are unquoted
*/
function stringToInt(jsonStruct, keys) {
let result = jsonStruct;
for (const key of keys) {
result = result.replace(new RegExp(`"${key}":\\s*"([0-9]+)"`, 'g'), `"${key}":$1`);
}
return result;
}
exports.stringToInt = stringToInt;
/**
* A transformer that converts all the values provided as keys to

@@ -29,0 +47,0 @@ * string values.

{
"name": "@concordium/node-sdk",
"version": "1.0.0",
"version": "1.1.0",
"description": "Helpers for interacting with the Concordium node",

@@ -5,0 +5,0 @@ "repository": {

@@ -916,2 +916,42 @@ # concordium-node-sdk-js

## InvokeContract
Used to simulate a contract update, and to trigger view functions.
```js
const blockHash = "7f7409679e53875567e2ae812c9fcefe90ced8961d08554756f42bf268a42749";
const contractAddress = { index: 1n, subindex: 0n };
const invoker = new AccountAddress('3tXiu8d4CWeuC12irAB7YVb1hzp3YxsmmmNzzkdujCPqQ9EjDm');
const result = await client.invokeContract(
blockHash,
{
invoker: invoker,
contract: contractAddress,
method: 'PiggyBank.smash',
amount: undefined,
parameter: undefined,
energy: 30000n,
}
);
if (!result) {
// The node could not attempt the invocation, most likely the contract doesn't exist.
}
if (result.tag === 'failure') {
// Invoke was unsuccesful
const rejectReason = result.reason; // Describes why the update failed;
...
} else {
const events = result.events; // a list of events that would be generated by the update
const returnValue = result.returnValue; // If the invoked method has return value
...
}
```
Note that some of the parts of the context are optional:
- amount: defaults to 0
- energy: defaults to 10 million
- parameter: defaults to no parameters
- invoker: uses the zero account address, which can be used instead of finding a random address.
## Deserialize contract state

@@ -918,0 +958,0 @@ The following example demonstrates how to deserialize a contract's state: