@alephium/web3 0.6.6 → 0.7.0

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.
@@ -541,6 +541,12 @@ export interface MinerAddressesInfo {
541
541
  addresses: AddressInfo[];
542
542
  }
543
543
  export declare type MisbehaviorAction = Ban | Unban;
544
+ export interface MultipleCallContract {
545
+ calls: CallContract[];
546
+ }
547
+ export interface MultipleCallContractResult {
548
+ results: CallContractResult[];
549
+ }
544
550
  export interface NodeInfo {
545
551
  buildInfo: BuildInfo;
546
552
  upnp: boolean;
@@ -674,6 +680,8 @@ export interface TestContract {
674
680
  group?: number;
675
681
  /** @format block-hash */
676
682
  blockHash?: string;
683
+ /** @format int64 */
684
+ blockTimeStamp?: number;
677
685
  /** @format 32-byte-hash */
678
686
  txId?: string;
679
687
  /** @format address */
@@ -920,7 +928,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
920
928
  }
921
929
  /**
922
930
  * @title Alephium API
923
- * @version 1.7.1
931
+ * @version 1.7.3
924
932
  * @baseUrl ../
925
933
  */
926
934
  export declare class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
@@ -1381,7 +1389,7 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
1381
1389
  *
1382
1390
  * @tags Transactions
1383
1391
  * @name PostTransactionsSweepAddressBuild
1384
- * @summary Build unsigned transactions to send all unlocked balanced of one address to another address
1392
+ * @summary Build unsigned transactions to send all unlocked ALPH and token balances of one address to another address
1385
1393
  * @request POST:/transactions/sweep-address/build
1386
1394
  */
1387
1395
  postTransactionsSweepAddressBuild: (data: BuildSweepAddressTransactions, params?: RequestParams) => Promise<BuildSweepAddressTransactionsResult>;
@@ -1549,6 +1557,15 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
1549
1557
  * @request POST:/contracts/call-contract
1550
1558
  */
1551
1559
  postContractsCallContract: (data: CallContract, params?: RequestParams) => Promise<CallContractResult>;
1560
+ /**
1561
+ * No description
1562
+ *
1563
+ * @tags Contracts
1564
+ * @name PostContractsMulticallContract
1565
+ * @summary Multiple call contract
1566
+ * @request POST:/contracts/multicall-contract
1567
+ */
1568
+ postContractsMulticallContract: (data: MultipleCallContract, params?: RequestParams) => Promise<MultipleCallContractResult>;
1552
1569
  };
1553
1570
  multisig: {
1554
1571
  /**
@@ -151,7 +151,7 @@ class HttpClient {
151
151
  exports.HttpClient = HttpClient;
152
152
  /**
153
153
  * @title Alephium API
154
- * @version 1.7.1
154
+ * @version 1.7.3
155
155
  * @baseUrl ../
156
156
  */
157
157
  class Api extends HttpClient {
@@ -801,7 +801,7 @@ class Api extends HttpClient {
801
801
  *
802
802
  * @tags Transactions
803
803
  * @name PostTransactionsSweepAddressBuild
804
- * @summary Build unsigned transactions to send all unlocked balanced of one address to another address
804
+ * @summary Build unsigned transactions to send all unlocked ALPH and token balances of one address to another address
805
805
  * @request POST:/transactions/sweep-address/build
806
806
  */
807
807
  postTransactionsSweepAddressBuild: (data, params = {}) => this.request({
@@ -1058,6 +1058,22 @@ class Api extends HttpClient {
1058
1058
  type: ContentType.Json,
1059
1059
  format: 'json',
1060
1060
  ...params
1061
+ }).then(utils_1.convertHttpResponse),
1062
+ /**
1063
+ * No description
1064
+ *
1065
+ * @tags Contracts
1066
+ * @name PostContractsMulticallContract
1067
+ * @summary Multiple call contract
1068
+ * @request POST:/contracts/multicall-contract
1069
+ */
1070
+ postContractsMulticallContract: (data, params = {}) => this.request({
1071
+ path: `/contracts/multicall-contract`,
1072
+ method: 'POST',
1073
+ body: data,
1074
+ type: ContentType.Json,
1075
+ format: 'json',
1076
+ ...params
1061
1077
  }).then(utils_1.convertHttpResponse)
1062
1078
  };
1063
1079
  this.multisig = {
@@ -1,5 +1,6 @@
1
- import { ApiRequestArguments, ApiRequestHandler } from './types';
1
+ import { ApiRequestArguments, ApiRequestHandler, TokenMetaData } from './types';
2
2
  import { Api as NodeApi } from './api-alephium';
3
+ import { HexString } from '../contract';
3
4
  export declare class NodeProvider {
4
5
  readonly wallets: NodeApi<string>['wallets'];
5
6
  readonly infos: NodeApi<string>['infos'];
@@ -18,4 +19,5 @@ export declare class NodeProvider {
18
19
  request: (args: ApiRequestArguments) => Promise<any>;
19
20
  static Proxy(nodeProvider: NodeProvider): NodeProvider;
20
21
  static Remote(handler: ApiRequestHandler): NodeProvider;
22
+ fetchStdTokenMetaData: (tokenId: HexString) => Promise<TokenMetaData>;
21
23
  }
@@ -21,6 +21,7 @@ exports.NodeProvider = void 0;
21
21
  const types_1 = require("./types");
22
22
  const api_alephium_1 = require("./api-alephium");
23
23
  const utils_1 = require("./utils");
24
+ const utils_2 = require("../utils");
24
25
  function initializeNodeApi(baseUrl, apiKey, customFetch) {
25
26
  const nodeApi = new api_alephium_1.Api({
26
27
  baseUrl: baseUrl,
@@ -36,9 +37,17 @@ class NodeProvider {
36
37
  this.request = (args) => {
37
38
  return (0, types_1.request)(this, args);
38
39
  };
40
+ // Only use this when the token is following the standard token interface
41
+ this.fetchStdTokenMetaData = async (tokenId) => {
42
+ return fetchStdTokenMetaData(this.contracts, tokenId);
43
+ };
39
44
  let nodeApi;
40
45
  if (typeof param0 === 'string') {
41
- nodeApi = initializeNodeApi(param0, apiKey, customFetch);
46
+ const api = initializeNodeApi(param0, apiKey, customFetch);
47
+ nodeApi = {
48
+ ...api,
49
+ fetchStdTokenMetaData: async (tokenId) => fetchStdTokenMetaData(api.contracts, tokenId)
50
+ };
42
51
  }
43
52
  else if (typeof param0 === 'function') {
44
53
  nodeApi = new NodeProvider('https://1.2.3.4:0');
@@ -68,3 +77,17 @@ class NodeProvider {
68
77
  }
69
78
  }
70
79
  exports.NodeProvider = NodeProvider;
80
+ async function fetchStdTokenMetaData(contractAPI, tokenId) {
81
+ const group = 0;
82
+ const address = (0, utils_2.addressFromTokenId)(tokenId);
83
+ const calls = Array.from([0, 1, 2, 3], (index) => ({ methodIndex: index, group: group, address: address }));
84
+ const result = await contractAPI.postContractsMulticallContract({
85
+ calls: calls
86
+ });
87
+ return {
88
+ symbol: result.results[0].returns[0].value,
89
+ name: result.results[1].returns[0].value,
90
+ decimals: Number(result.results[2].returns[0].value),
91
+ totalSupply: BigInt(result.results[3].returns[0].value)
92
+ };
93
+ }
@@ -30,3 +30,9 @@ export interface ApiRequestArguments {
30
30
  export declare type ApiRequestHandler = (args: ApiRequestArguments) => Promise<any>;
31
31
  export declare function forwardRequests(api: Record<string, any>, handler: ApiRequestHandler): void;
32
32
  export declare function request(provider: Record<string, any>, args: ApiRequestArguments): Promise<any>;
33
+ export interface TokenMetaData {
34
+ name: string;
35
+ symbol: string;
36
+ decimals: number;
37
+ totalSupply: Number256;
38
+ }
@@ -169,6 +169,7 @@ export interface TestContractParams<F extends Fields = Fields, A extends Argumen
169
169
  group?: number;
170
170
  address?: string;
171
171
  blockHash?: string;
172
+ blockTimeStamp?: number;
172
173
  txId?: string;
173
174
  initialFields: F;
174
175
  initialAsset?: Asset;
@@ -287,5 +288,6 @@ export declare function decodeEvent<F extends Fields, M extends ContractEvent<F>
287
288
  export declare function subscribeContractEvent<F extends Fields, M extends ContractEvent<F>>(contract: Contract, instance: ContractInstance, options: SubscribeOptions<M>, eventName: string, fromCount?: number): EventSubscription;
288
289
  export declare function subscribeContractEvents(contract: Contract, instance: ContractInstance, options: SubscribeOptions<ContractEvent<any>>, fromCount?: number): EventSubscription;
289
290
  export declare function callMethod<I, F extends Fields, A extends Arguments, R>(contract: ContractFactory<I, F>, instance: ContractInstance, methodName: string, params: Optional<CallContractParams<A>, 'args'>): Promise<CallContractResult<R>>;
291
+ export declare function multicallMethods<I, F extends Fields>(contract: ContractFactory<I, F>, instance: ContractInstance, calls: Record<string, Optional<CallContractParams<any>, 'args'>>): Promise<Record<string, CallContractResult<any>>>;
290
292
  export declare function getContractEventsCurrentCount(contractAddress: Address): Promise<number>;
291
293
  export {};
@@ -43,7 +43,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
43
43
  return (mod && mod.__esModule) ? mod : { "default": mod };
44
44
  };
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.getContractEventsCurrentCount = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddress = exports.CreateContractEventAddress = exports.ContractFactory = exports.randomTxId = exports.toApiVals = exports.Script = exports.Contract = exports.Artifact = exports.Project = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = void 0;
46
+ exports.getContractEventsCurrentCount = exports.multicallMethods = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddress = exports.CreateContractEventAddress = exports.ContractFactory = exports.randomTxId = exports.toApiVals = exports.Script = exports.Contract = exports.Artifact = exports.Project = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = void 0;
47
47
  const buffer_1 = require("buffer/");
48
48
  const crypto_1 = require("crypto");
49
49
  const fs_1 = __importDefault(require("fs"));
@@ -551,6 +551,9 @@ class Contract extends Artifact {
551
551
  const mutFields = params.initialFields === undefined ? [] : extractFields(params.initialFields, this.fieldsSig, true);
552
552
  return {
553
553
  group: params.group,
554
+ blockHash: params.blockHash,
555
+ blockTimeStamp: params.blockTimeStamp,
556
+ txId: params.txId,
554
557
  address: params.address,
555
558
  bytecode: this.bytecodeDebug,
556
559
  initialImmFields: immFields,
@@ -1044,6 +1047,25 @@ async function callMethod(contract, instance, methodName, params) {
1044
1047
  return callResult;
1045
1048
  }
1046
1049
  exports.callMethod = callMethod;
1050
+ async function multicallMethods(contract, instance, calls) {
1051
+ const callEntries = Object.entries(calls);
1052
+ const callsParams = callEntries.map((entry) => {
1053
+ const [methodName, params] = entry;
1054
+ const methodIndex = contract.contract.getMethodIndex(methodName);
1055
+ const txId = params?.txId ?? randomTxId();
1056
+ return contract.contract.toApiCallContract({ ...params, txId: txId, args: params.args === undefined ? {} : params.args }, instance.groupIndex, instance.address, methodIndex);
1057
+ });
1058
+ const result = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsMulticallContract({ calls: callsParams });
1059
+ const callsResult = {};
1060
+ callsParams.forEach((call, index) => {
1061
+ const methodIndex = call.methodIndex;
1062
+ const callResult = result.results[`${methodIndex}`];
1063
+ const methodName = callEntries[`${index}`][`0`];
1064
+ callsResult[`${methodName}`] = contract.contract.fromApiCallContractResult(callResult, call.txId, methodIndex);
1065
+ });
1066
+ return callsResult;
1067
+ }
1068
+ exports.multicallMethods = multicallMethods;
1047
1069
  async function getContractEventsCurrentCount(contractAddress) {
1048
1070
  return (0, global_1.getCurrentNodeProvider)()
1049
1071
  .events.getEventsContractContractaddressCurrentCount(contractAddress)
@@ -19,6 +19,7 @@ export declare function groupOfPrivateKey(privateKey: string, keyType?: KeyType)
19
19
  export declare function publicKeyFromPrivateKey(privateKey: string, _keyType?: KeyType): string;
20
20
  export declare function addressFromPublicKey(publicKey: string, _keyType?: KeyType): string;
21
21
  export declare function addressFromContractId(contractId: string): string;
22
+ export declare function addressFromTokenId(tokenId: string): string;
22
23
  export declare function contractIdFromTx(txId: string, outputIndex: number): string;
23
24
  export declare function subContractId(parentContractId: string, pathInHex: string, group: number): string;
24
25
  export declare function blockChainIndex(blockHash: HexString): {
@@ -20,7 +20,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  return (mod && mod.__esModule) ? mod : { "default": mod };
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.assertType = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.subContractId = exports.contractIdFromTx = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isHexString = exports.xorByte = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = void 0;
23
+ exports.assertType = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isHexString = exports.xorByte = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = void 0;
24
24
  const elliptic_1 = require("elliptic");
25
25
  const bn_js_1 = __importDefault(require("bn.js"));
26
26
  const blakejs_1 = __importDefault(require("blakejs"));
@@ -191,6 +191,11 @@ function addressFromContractId(contractId) {
191
191
  return bs58_1.default.encode(bytes);
192
192
  }
193
193
  exports.addressFromContractId = addressFromContractId;
194
+ function addressFromTokenId(tokenId) {
195
+ const contractId = tokenId; // contract ID is the same as token ID
196
+ return addressFromContractId(contractId);
197
+ }
198
+ exports.addressFromTokenId = addressFromTokenId;
194
199
  function contractIdFromTx(txId, outputIndex) {
195
200
  const txIdBin = hexToBinUnsafe(txId);
196
201
  const data = buffer_1.Buffer.concat([txIdBin, buffer_1.Buffer.from([outputIndex])]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "0.6.6",
3
+ "version": "0.7.0",
4
4
  "description": "A JS/TS library to interact with the Alephium platform",
5
5
  "license": "GPL",
6
6
  "main": "dist/src/index.js",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "author": "Alephium dev <dev@alephium.org>",
29
29
  "config": {
30
- "alephium_version": "1.7.1",
30
+ "alephium_version": "1.7.3",
31
31
  "explorer_backend_version": "1.13.0"
32
32
  },
33
33
  "scripts": {
@@ -618,6 +618,14 @@ export interface MinerAddressesInfo {
618
618
 
619
619
  export type MisbehaviorAction = Ban | Unban
620
620
 
621
+ export interface MultipleCallContract {
622
+ calls: CallContract[]
623
+ }
624
+
625
+ export interface MultipleCallContractResult {
626
+ results: CallContractResult[]
627
+ }
628
+
621
629
  export interface NodeInfo {
622
630
  buildInfo: BuildInfo
623
631
  upnp: boolean
@@ -775,6 +783,8 @@ export interface TestContract {
775
783
  group?: number
776
784
  /** @format block-hash */
777
785
  blockHash?: string
786
+ /** @format int64 */
787
+ blockTimeStamp?: number
778
788
  /** @format 32-byte-hash */
779
789
  txId?: string
780
790
  /** @format address */
@@ -1206,7 +1216,7 @@ export class HttpClient<SecurityDataType = unknown> {
1206
1216
 
1207
1217
  /**
1208
1218
  * @title Alephium API
1209
- * @version 1.7.1
1219
+ * @version 1.7.3
1210
1220
  * @baseUrl ../
1211
1221
  */
1212
1222
  export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
@@ -2045,7 +2055,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
2045
2055
  *
2046
2056
  * @tags Transactions
2047
2057
  * @name PostTransactionsSweepAddressBuild
2048
- * @summary Build unsigned transactions to send all unlocked balanced of one address to another address
2058
+ * @summary Build unsigned transactions to send all unlocked ALPH and token balances of one address to another address
2049
2059
  * @request POST:/transactions/sweep-address/build
2050
2060
  */
2051
2061
  postTransactionsSweepAddressBuild: (data: BuildSweepAddressTransactions, params: RequestParams = {}) =>
@@ -2391,7 +2401,28 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
2391
2401
  format: 'json',
2392
2402
  ...params
2393
2403
  }
2394
- ).then(convertHttpResponse)
2404
+ ).then(convertHttpResponse),
2405
+
2406
+ /**
2407
+ * No description
2408
+ *
2409
+ * @tags Contracts
2410
+ * @name PostContractsMulticallContract
2411
+ * @summary Multiple call contract
2412
+ * @request POST:/contracts/multicall-contract
2413
+ */
2414
+ postContractsMulticallContract: (data: MultipleCallContract, params: RequestParams = {}) =>
2415
+ this.request<
2416
+ MultipleCallContractResult,
2417
+ BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable
2418
+ >({
2419
+ path: `/contracts/multicall-contract`,
2420
+ method: 'POST',
2421
+ body: data,
2422
+ type: ContentType.Json,
2423
+ format: 'json',
2424
+ ...params
2425
+ }).then(convertHttpResponse)
2395
2426
  }
2396
2427
  multisig = {
2397
2428
  /**
@@ -16,9 +16,11 @@ You should have received a copy of the GNU Lesser General Public License
16
16
  along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
- import { ApiRequestArguments, ApiRequestHandler, forwardRequests, request } from './types'
19
+ import { ApiRequestArguments, ApiRequestHandler, forwardRequests, request, TokenMetaData } from './types'
20
20
  import { Api as NodeApi } from './api-alephium'
21
21
  import { DEFAULT_THROTTLE_FETCH } from './utils'
22
+ import { HexString } from '../contract'
23
+ import { addressFromTokenId } from '../utils'
22
24
 
23
25
  function initializeNodeApi(baseUrl: string, apiKey?: string, customFetch?: typeof fetch): NodeApi<string> {
24
26
  const nodeApi = new NodeApi<string>({
@@ -50,7 +52,11 @@ export class NodeProvider {
50
52
  constructor(param0: string | NodeProvider | ApiRequestHandler, apiKey?: string, customFetch?: typeof fetch) {
51
53
  let nodeApi: NodeProvider
52
54
  if (typeof param0 === 'string') {
53
- nodeApi = initializeNodeApi(param0, apiKey, customFetch)
55
+ const api = initializeNodeApi(param0, apiKey, customFetch)
56
+ nodeApi = {
57
+ ...api,
58
+ fetchStdTokenMetaData: async (tokenId: string) => fetchStdTokenMetaData(api.contracts, tokenId)
59
+ }
54
60
  } else if (typeof param0 === 'function') {
55
61
  nodeApi = new NodeProvider('https://1.2.3.4:0')
56
62
  forwardRequests(nodeApi, param0 as ApiRequestHandler)
@@ -83,4 +89,27 @@ export class NodeProvider {
83
89
  static Remote(handler: ApiRequestHandler): NodeProvider {
84
90
  return new NodeProvider(handler)
85
91
  }
92
+
93
+ // Only use this when the token is following the standard token interface
94
+ fetchStdTokenMetaData = async (tokenId: HexString): Promise<TokenMetaData> => {
95
+ return fetchStdTokenMetaData(this.contracts, tokenId)
96
+ }
97
+ }
98
+
99
+ async function fetchStdTokenMetaData(
100
+ contractAPI: NodeApi<string>['contracts'],
101
+ tokenId: HexString
102
+ ): Promise<TokenMetaData> {
103
+ const group = 0
104
+ const address = addressFromTokenId(tokenId)
105
+ const calls = Array.from([0, 1, 2, 3], (index) => ({ methodIndex: index, group: group, address: address }))
106
+ const result = await contractAPI.postContractsMulticallContract({
107
+ calls: calls
108
+ })
109
+ return {
110
+ symbol: result.results[0].returns[0].value as any as string,
111
+ name: result.results[1].returns[0].value as any as string,
112
+ decimals: Number(result.results[2].returns[0].value as any as string),
113
+ totalSupply: BigInt(result.results[3].returns[0].value as any as string)
114
+ }
86
115
  }
package/src/api/types.ts CHANGED
@@ -268,3 +268,10 @@ export async function request(provider: Record<string, any>, args: ApiRequestArg
268
268
  const call = provider[`${args.path}`][`${args.method}`] as (...any) => Promise<any>
269
269
  return call(...args.params)
270
270
  }
271
+
272
+ export interface TokenMetaData {
273
+ name: string
274
+ symbol: string
275
+ decimals: number
276
+ totalSupply: Number256
277
+ }
@@ -818,6 +818,9 @@ export class Contract extends Artifact {
818
818
  params.initialFields === undefined ? [] : extractFields(params.initialFields, this.fieldsSig, true)
819
819
  return {
820
820
  group: params.group,
821
+ blockHash: params.blockHash,
822
+ blockTimeStamp: params.blockTimeStamp,
823
+ txId: params.txId,
821
824
  address: params.address,
822
825
  bytecode: this.bytecodeDebug,
823
826
  initialImmFields: immFields,
@@ -1210,6 +1213,7 @@ export interface TestContractParams<F extends Fields = Fields, A extends Argumen
1210
1213
  group?: number // default 0
1211
1214
  address?: string
1212
1215
  blockHash?: string
1216
+ blockTimeStamp?: number
1213
1217
  txId?: string
1214
1218
  initialFields: F
1215
1219
  initialAsset?: Asset // default 1 ALPH
@@ -1602,6 +1606,38 @@ export async function callMethod<I, F extends Fields, A extends Arguments, R>(
1602
1606
  return callResult as CallContractResult<R>
1603
1607
  }
1604
1608
 
1609
+ export async function multicallMethods<I, F extends Fields>(
1610
+ contract: ContractFactory<I, F>,
1611
+ instance: ContractInstance,
1612
+ calls: Record<string, Optional<CallContractParams<any>, 'args'>>
1613
+ ): Promise<Record<string, CallContractResult<any>>> {
1614
+ const callEntries = Object.entries(calls)
1615
+ const callsParams = callEntries.map((entry) => {
1616
+ const [methodName, params] = entry
1617
+ const methodIndex = contract.contract.getMethodIndex(methodName)
1618
+ const txId = params?.txId ?? randomTxId()
1619
+ return contract.contract.toApiCallContract(
1620
+ { ...params, txId: txId, args: params.args === undefined ? {} : params.args },
1621
+ instance.groupIndex,
1622
+ instance.address,
1623
+ methodIndex
1624
+ )
1625
+ })
1626
+ const result = await getCurrentNodeProvider().contracts.postContractsMulticallContract({ calls: callsParams })
1627
+ const callsResult: Record<string, CallContractResult<any>> = {}
1628
+ callsParams.forEach((call, index) => {
1629
+ const methodIndex = call.methodIndex
1630
+ const callResult = result.results[`${methodIndex}`]
1631
+ const methodName = callEntries[`${index}`][`0`]
1632
+ callsResult[`${methodName}`] = contract.contract.fromApiCallContractResult(
1633
+ callResult,
1634
+ call.txId!,
1635
+ methodIndex
1636
+ ) as CallContractResult<any>
1637
+ })
1638
+ return callsResult
1639
+ }
1640
+
1605
1641
  export async function getContractEventsCurrentCount(contractAddress: Address): Promise<number> {
1606
1642
  return getCurrentNodeProvider()
1607
1643
  .events.getEventsContractContractaddressCurrentCount(contractAddress)
@@ -197,6 +197,11 @@ export function addressFromContractId(contractId: string): string {
197
197
  return bs58.encode(bytes)
198
198
  }
199
199
 
200
+ export function addressFromTokenId(tokenId: string): string {
201
+ const contractId = tokenId // contract ID is the same as token ID
202
+ return addressFromContractId(contractId)
203
+ }
204
+
200
205
  export function contractIdFromTx(txId: string, outputIndex: number): string {
201
206
  const txIdBin = hexToBinUnsafe(txId)
202
207
  const data = Buffer.concat([txIdBin, Buffer.from([outputIndex])])