@alephium/web3 0.5.0-rc.0 → 0.5.0-rc.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/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.js +2 -1
- package/dist/src/contract/contract.d.ts +28 -13
- package/dist/src/contract/contract.js +136 -5
- package/dist/src/utils/utils.d.ts +1 -0
- package/package.json +2 -2
- package/src/constants.ts +1 -0
- package/src/contract/contract.ts +239 -18
- package/src/utils/utils.ts +1 -0
package/dist/src/constants.d.ts
CHANGED
package/dist/src/constants.js
CHANGED
|
@@ -17,8 +17,9 @@ You should have received a copy of the GNU Lesser General Public License
|
|
|
17
17
|
along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.ONE_ALPH = exports.ALPH_TOKEN_ID = exports.MIN_UTXO_SET_AMOUNT = exports.TOTAL_NUMBER_OF_GROUPS = void 0;
|
|
20
|
+
exports.DUST_AMOUNT = exports.ONE_ALPH = exports.ALPH_TOKEN_ID = exports.MIN_UTXO_SET_AMOUNT = exports.TOTAL_NUMBER_OF_GROUPS = void 0;
|
|
21
21
|
exports.TOTAL_NUMBER_OF_GROUPS = 4;
|
|
22
22
|
exports.MIN_UTXO_SET_AMOUNT = BigInt(1000000000000);
|
|
23
23
|
exports.ALPH_TOKEN_ID = ''.padStart(64, '0');
|
|
24
24
|
exports.ONE_ALPH = 10n ** 18n;
|
|
25
|
+
exports.DUST_AMOUNT = 10n ** 15n;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { NamedVals, node, Number256, Token
|
|
2
|
-
import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScriptTxParams, SignerProvider } from '../signer';
|
|
3
|
-
import { SubscribeOptions } from '../utils';
|
|
1
|
+
import { NamedVals, node, Number256, Token } from '../api';
|
|
2
|
+
import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScriptTxParams, SignerProvider, Address } from '../signer';
|
|
3
|
+
import { SubscribeOptions, Optional } from '../utils';
|
|
4
4
|
import { EventSubscription } from './events';
|
|
5
5
|
export declare type FieldsSig = node.FieldsSig;
|
|
6
6
|
export declare type EventSig = node.EventSig;
|
|
@@ -127,12 +127,12 @@ export declare class Contract extends Artifact {
|
|
|
127
127
|
static ContractDestroyedEventIndex: number;
|
|
128
128
|
static ContractDestroyedEvent: EventSig;
|
|
129
129
|
static fromApiEvent(event: node.ContractEventByTxId, codeHash: string | undefined, txId: string): ContractEvent;
|
|
130
|
-
fromApiTestContractResult(
|
|
130
|
+
fromApiTestContractResult(methodName: string, result: node.TestContractResult, txId: string): TestContractResult<unknown>;
|
|
131
131
|
txParamsForDeployment<P extends Fields>(signer: SignerProvider, params: DeployContractParams<P>): Promise<SignDeployContractTxParams>;
|
|
132
132
|
buildByteCodeToDeploy(initialFields: Fields): string;
|
|
133
133
|
static fromApiEvents(events: node.ContractEventByTxId[], addressToCodeHash: Map<string, string>, txId: string): ContractEvent[];
|
|
134
134
|
toApiCallContract<T extends Arguments>(params: CallContractParams<T>, groupIndex: number, contractAddress: string, methodIndex: number): node.CallContract;
|
|
135
|
-
fromApiCallContractResult(result: node.CallContractResult, txId: string, methodIndex: number): CallContractResult
|
|
135
|
+
fromApiCallContractResult(result: node.CallContractResult, txId: string, methodIndex: number): CallContractResult<unknown>;
|
|
136
136
|
}
|
|
137
137
|
export declare class Script extends Artifact {
|
|
138
138
|
readonly bytecodeTemplate: string;
|
|
@@ -185,10 +185,10 @@ export interface ContractEvent<T extends Fields = Fields> {
|
|
|
185
185
|
fields: T;
|
|
186
186
|
}
|
|
187
187
|
export declare type DebugMessage = node.DebugMessage;
|
|
188
|
-
export interface TestContractResult {
|
|
188
|
+
export interface TestContractResult<R> {
|
|
189
189
|
contractId: string;
|
|
190
190
|
contractAddress: string;
|
|
191
|
-
returns:
|
|
191
|
+
returns: R;
|
|
192
192
|
gasUsed: number;
|
|
193
193
|
contracts: ContractState[];
|
|
194
194
|
txOutputs: Output[];
|
|
@@ -220,11 +220,12 @@ export interface DeployContractParams<P extends Fields = Fields> {
|
|
|
220
220
|
export declare type DeployContractResult<T> = SignDeployContractTxResult & {
|
|
221
221
|
instance: T;
|
|
222
222
|
};
|
|
223
|
-
export declare abstract class ContractFactory<
|
|
223
|
+
export declare abstract class ContractFactory<I, F extends Fields = Fields> {
|
|
224
224
|
readonly contract: Contract;
|
|
225
225
|
constructor(contract: Contract);
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
abstract at(address: string): I;
|
|
227
|
+
deploy(signer: SignerProvider, deployParams: DeployContractParams<F>): Promise<DeployContractResult<I>>;
|
|
228
|
+
stateForTest(initFields: F, asset?: Asset, address?: string): ContractState<F>;
|
|
228
229
|
}
|
|
229
230
|
export interface ExecuteScriptParams<P extends Fields = Fields> {
|
|
230
231
|
initialFields: P;
|
|
@@ -248,8 +249,8 @@ export interface CallContractParams<T extends Arguments = Arguments> {
|
|
|
248
249
|
existingContracts?: string[];
|
|
249
250
|
inputAssets?: node.TestInputAsset[];
|
|
250
251
|
}
|
|
251
|
-
export interface CallContractResult {
|
|
252
|
-
returns:
|
|
252
|
+
export interface CallContractResult<R> {
|
|
253
|
+
returns: R;
|
|
253
254
|
gasUsed: number;
|
|
254
255
|
contracts: ContractState[];
|
|
255
256
|
txInputs: string[];
|
|
@@ -264,5 +265,19 @@ export declare type ContractDestroyedEvent = ContractEvent<{
|
|
|
264
265
|
}>;
|
|
265
266
|
export declare function decodeContractCreatedEvent(event: node.ContractEvent): Omit<ContractCreatedEvent, 'contractAddress'>;
|
|
266
267
|
export declare function decodeContractDestroyedEvent(event: node.ContractEvent): Omit<ContractDestroyedEvent, 'contractAddress'>;
|
|
267
|
-
export declare function subscribeEventsFromContract<T extends Fields
|
|
268
|
+
export declare function subscribeEventsFromContract<T extends Fields, M extends ContractEvent<T>>(options: SubscribeOptions<M>, address: string, eventIndex: number, decodeFunc: (event: node.ContractEvent) => M, fromCount?: number): EventSubscription;
|
|
269
|
+
export declare function testMethod<I, F extends Fields, A extends Arguments, R>(contract: ContractFactory<I, F>, methodName: string, params: Optional<TestContractParams<F, A>, 'testArgs' | 'initialFields'>): Promise<TestContractResult<R>>;
|
|
270
|
+
export declare abstract class ContractInstance {
|
|
271
|
+
readonly address: Address;
|
|
272
|
+
readonly contractId: string;
|
|
273
|
+
readonly groupIndex: number;
|
|
274
|
+
constructor(address: Address);
|
|
275
|
+
}
|
|
276
|
+
export declare function fetchContractState<F extends Fields, I extends ContractInstance>(contract: ContractFactory<I, F>, instance: ContractInstance): Promise<ContractState<F>>;
|
|
277
|
+
export declare function subscribeContractCreatedEvent(instance: ContractInstance, options: SubscribeOptions<ContractCreatedEvent>, fromCount?: number): EventSubscription;
|
|
278
|
+
export declare function subscribeContractDestroyedEvent(instance: ContractInstance, options: SubscribeOptions<ContractDestroyedEvent>, fromCount?: number): EventSubscription;
|
|
279
|
+
export declare function decodeEvent<F extends Fields, M extends ContractEvent<F>>(contract: Contract, instance: ContractInstance, event: node.ContractEvent, targetEventIndex: number): M;
|
|
280
|
+
export declare function subscribeContractEvent<F extends Fields, M extends ContractEvent<F>>(contract: Contract, instance: ContractInstance, options: SubscribeOptions<M>, eventName: string, fromCount?: number): EventSubscription;
|
|
281
|
+
export declare function subscribeAllEvents(contract: Contract, instance: ContractInstance, options: SubscribeOptions<ContractEvent<any>>, fromCount?: number): EventSubscription;
|
|
282
|
+
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>>;
|
|
268
283
|
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.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = 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.callMethod = exports.subscribeAllEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.testMethod = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = 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"));
|
|
@@ -54,6 +54,7 @@ const utils_1 = require("../utils");
|
|
|
54
54
|
const global_1 = require("../global");
|
|
55
55
|
const path = __importStar(require("path"));
|
|
56
56
|
const events_1 = require("./events");
|
|
57
|
+
const constants_1 = require("../constants");
|
|
57
58
|
var SourceKind;
|
|
58
59
|
(function (SourceKind) {
|
|
59
60
|
SourceKind[SourceKind["Contract"] = 0] = "Contract";
|
|
@@ -598,14 +599,18 @@ class Contract extends Artifact {
|
|
|
598
599
|
fields: fromApiEventFields(event.fields, eventSig)
|
|
599
600
|
};
|
|
600
601
|
}
|
|
601
|
-
fromApiTestContractResult(
|
|
602
|
+
fromApiTestContractResult(methodName, result, txId) {
|
|
603
|
+
const methodIndex = this.functions.findIndex((sig) => sig.name === methodName);
|
|
604
|
+
const returnTypes = this.functions[`${methodIndex}`].returnTypes;
|
|
605
|
+
const rawReturn = (0, api_1.fromApiArray)(result.returns, returnTypes);
|
|
606
|
+
const returns = rawReturn.length === 0 ? null : rawReturn.length === 1 ? rawReturn[0] : rawReturn;
|
|
602
607
|
const addressToCodeHash = new Map();
|
|
603
608
|
addressToCodeHash.set(result.address, result.codeHash);
|
|
604
609
|
result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash));
|
|
605
610
|
return {
|
|
606
611
|
contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(result.address)),
|
|
607
612
|
contractAddress: result.address,
|
|
608
|
-
returns:
|
|
613
|
+
returns: returns,
|
|
609
614
|
gasUsed: result.gasUsed,
|
|
610
615
|
contracts: result.contracts.map((contract) => Contract.fromApiContractState(contract)),
|
|
611
616
|
txOutputs: result.txOutputs.map(fromApiOutput),
|
|
@@ -653,10 +658,11 @@ class Contract extends Artifact {
|
|
|
653
658
|
};
|
|
654
659
|
}
|
|
655
660
|
fromApiCallContractResult(result, txId, methodIndex) {
|
|
661
|
+
const returnTypes = this.functions[`${methodIndex}`].returnTypes;
|
|
662
|
+
const rawReturn = (0, api_1.fromApiArray)(result.returns, returnTypes);
|
|
663
|
+
const returns = rawReturn.length === 0 ? null : rawReturn.length === 1 ? rawReturn[0] : rawReturn;
|
|
656
664
|
const addressToCodeHash = new Map();
|
|
657
665
|
result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash));
|
|
658
|
-
const functionSig = this.functions[`${methodIndex}`];
|
|
659
|
-
const returns = (0, api_1.fromApiArray)(result.returns, functionSig.returnTypes);
|
|
660
666
|
return {
|
|
661
667
|
returns: returns,
|
|
662
668
|
gasUsed: result.gasUsed,
|
|
@@ -856,6 +862,14 @@ class ContractFactory {
|
|
|
856
862
|
instance: this.at(result.contractAddress)
|
|
857
863
|
};
|
|
858
864
|
}
|
|
865
|
+
// This is used for testing contract functions
|
|
866
|
+
stateForTest(initFields, asset, address) {
|
|
867
|
+
const newAsset = {
|
|
868
|
+
alphAmount: asset?.alphAmount ?? constants_1.ONE_ALPH,
|
|
869
|
+
tokens: asset?.tokens
|
|
870
|
+
};
|
|
871
|
+
return this.contract.toState(initFields, newAsset, address);
|
|
872
|
+
}
|
|
859
873
|
}
|
|
860
874
|
exports.ContractFactory = ContractFactory;
|
|
861
875
|
function decodeFields(event, eventSig, eventIndex) {
|
|
@@ -904,3 +918,120 @@ function subscribeEventsFromContract(options, address, eventIndex, decodeFunc, f
|
|
|
904
918
|
return (0, events_1.subscribeToEvents)(opt, address, fromCount);
|
|
905
919
|
}
|
|
906
920
|
exports.subscribeEventsFromContract = subscribeEventsFromContract;
|
|
921
|
+
async function testMethod(contract, methodName, params) {
|
|
922
|
+
const txId = params?.txId ?? randomTxId();
|
|
923
|
+
const apiParams = contract.contract.toApiTestContractParams(methodName, {
|
|
924
|
+
...params,
|
|
925
|
+
txId: txId,
|
|
926
|
+
initialFields: params.initialFields === undefined ? {} : params.initialFields,
|
|
927
|
+
testArgs: params.testArgs === undefined ? {} : params.testArgs
|
|
928
|
+
});
|
|
929
|
+
const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
|
|
930
|
+
const testResult = contract.contract.fromApiTestContractResult(methodName, apiResult, txId);
|
|
931
|
+
contract.contract.printDebugMessages(methodName, testResult.debugMessages);
|
|
932
|
+
return testResult;
|
|
933
|
+
}
|
|
934
|
+
exports.testMethod = testMethod;
|
|
935
|
+
class ContractInstance {
|
|
936
|
+
constructor(address) {
|
|
937
|
+
this.address = address;
|
|
938
|
+
this.contractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
|
|
939
|
+
this.groupIndex = (0, utils_1.groupOfAddress)(address);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
exports.ContractInstance = ContractInstance;
|
|
943
|
+
async function fetchContractState(contract, instance) {
|
|
944
|
+
const contractState = await (0, global_1.getCurrentNodeProvider)().contracts.getContractsAddressState(instance.address, {
|
|
945
|
+
group: instance.groupIndex
|
|
946
|
+
});
|
|
947
|
+
const state = contract.contract.fromApiContractState(contractState);
|
|
948
|
+
return {
|
|
949
|
+
...state,
|
|
950
|
+
fields: state.fields
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
exports.fetchContractState = fetchContractState;
|
|
954
|
+
function subscribeContractCreatedEvent(instance, options, fromCount) {
|
|
955
|
+
return subscribeEventsFromContract(options, instance.address, Contract.ContractCreatedEventIndex, (event) => {
|
|
956
|
+
return {
|
|
957
|
+
...decodeContractCreatedEvent(event),
|
|
958
|
+
contractAddress: instance.address
|
|
959
|
+
};
|
|
960
|
+
}, fromCount);
|
|
961
|
+
}
|
|
962
|
+
exports.subscribeContractCreatedEvent = subscribeContractCreatedEvent;
|
|
963
|
+
function subscribeContractDestroyedEvent(instance, options, fromCount) {
|
|
964
|
+
return subscribeEventsFromContract(options, instance.address, Contract.ContractDestroyedEventIndex, (event) => {
|
|
965
|
+
return {
|
|
966
|
+
...decodeContractDestroyedEvent(event),
|
|
967
|
+
contractAddress: instance.address
|
|
968
|
+
};
|
|
969
|
+
}, fromCount);
|
|
970
|
+
}
|
|
971
|
+
exports.subscribeContractDestroyedEvent = subscribeContractDestroyedEvent;
|
|
972
|
+
function decodeEvent(contract, instance, event, targetEventIndex) {
|
|
973
|
+
if (event.eventIndex !== targetEventIndex &&
|
|
974
|
+
!(targetEventIndex >= 0 && targetEventIndex < contract.eventsSig.length)) {
|
|
975
|
+
throw new Error('Invalid event index: ' + event.eventIndex + ', expected: ' + targetEventIndex);
|
|
976
|
+
}
|
|
977
|
+
const eventSig = contract.eventsSig[`${targetEventIndex}`];
|
|
978
|
+
const fieldNames = eventSig.fieldNames;
|
|
979
|
+
const fieldTypes = eventSig.fieldTypes;
|
|
980
|
+
const fields = (0, api_1.fromApiVals)(event.fields, fieldNames, fieldTypes);
|
|
981
|
+
return {
|
|
982
|
+
contractAddress: instance.address,
|
|
983
|
+
blockHash: event.blockHash,
|
|
984
|
+
txId: event.txId,
|
|
985
|
+
eventIndex: event.eventIndex,
|
|
986
|
+
name: eventSig.name,
|
|
987
|
+
fields: fields
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
exports.decodeEvent = decodeEvent;
|
|
991
|
+
function subscribeContractEvent(contract, instance, options, eventName, fromCount) {
|
|
992
|
+
const eventIndex = contract.eventsSig.findIndex((sig) => sig.name === eventName);
|
|
993
|
+
return subscribeEventsFromContract(options, instance.address, eventIndex, (event) => decodeEvent(contract, instance, event, eventIndex), fromCount);
|
|
994
|
+
}
|
|
995
|
+
exports.subscribeContractEvent = subscribeContractEvent;
|
|
996
|
+
function subscribeAllEvents(contract, instance, options, fromCount) {
|
|
997
|
+
const messageCallback = (event) => {
|
|
998
|
+
switch (event.eventIndex) {
|
|
999
|
+
case Contract.ContractCreatedEventIndex: {
|
|
1000
|
+
return options.messageCallback({
|
|
1001
|
+
...decodeContractCreatedEvent(event),
|
|
1002
|
+
contractAddress: instance.address
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
case Contract.ContractDestroyedEventIndex: {
|
|
1006
|
+
return options.messageCallback({
|
|
1007
|
+
...decodeContractDestroyedEvent(event),
|
|
1008
|
+
contractAddress: instance.address
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
default:
|
|
1012
|
+
return options.messageCallback({
|
|
1013
|
+
...decodeEvent(contract, instance, event, event.eventIndex),
|
|
1014
|
+
contractAddress: instance.address
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
const errorCallback = (err, subscription) => {
|
|
1019
|
+
return options.errorCallback(err, subscription);
|
|
1020
|
+
};
|
|
1021
|
+
const opt = {
|
|
1022
|
+
pollingInterval: options.pollingInterval,
|
|
1023
|
+
messageCallback: messageCallback,
|
|
1024
|
+
errorCallback: errorCallback
|
|
1025
|
+
};
|
|
1026
|
+
return (0, events_1.subscribeToEvents)(opt, instance.address, fromCount);
|
|
1027
|
+
}
|
|
1028
|
+
exports.subscribeAllEvents = subscribeAllEvents;
|
|
1029
|
+
async function callMethod(contract, instance, methodName, params) {
|
|
1030
|
+
const methodIndex = contract.contract.getMethodIndex(methodName);
|
|
1031
|
+
const txId = params?.txId ?? randomTxId();
|
|
1032
|
+
const callParams = contract.contract.toApiCallContract({ ...params, txId: txId, args: params.args === undefined ? {} : params.args }, instance.groupIndex, instance.address, methodIndex);
|
|
1033
|
+
const result = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsCallContract(callParams);
|
|
1034
|
+
const callResult = contract.contract.fromApiCallContractResult(result, txId, methodIndex);
|
|
1035
|
+
return callResult;
|
|
1036
|
+
}
|
|
1037
|
+
exports.callMethod = callMethod;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alephium/web3",
|
|
3
|
-
"version": "0.5.0-rc.
|
|
3
|
+
"version": "0.5.0-rc.2",
|
|
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.0
|
|
30
|
+
"alephium_version": "1.7.0",
|
|
31
31
|
"explorer_backend_version": "1.12.0"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
package/src/constants.ts
CHANGED
package/src/contract/contract.ts
CHANGED
|
@@ -40,13 +40,25 @@ import {
|
|
|
40
40
|
SignDeployContractTxParams,
|
|
41
41
|
SignDeployContractTxResult,
|
|
42
42
|
SignExecuteScriptTxParams,
|
|
43
|
-
SignerProvider
|
|
43
|
+
SignerProvider,
|
|
44
|
+
Address
|
|
44
45
|
} from '../signer'
|
|
45
46
|
import * as ralph from './ralph'
|
|
46
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
bs58,
|
|
49
|
+
binToHex,
|
|
50
|
+
contractIdFromAddress,
|
|
51
|
+
SubscribeOptions,
|
|
52
|
+
Subscription,
|
|
53
|
+
assertType,
|
|
54
|
+
Eq,
|
|
55
|
+
Optional,
|
|
56
|
+
groupOfAddress
|
|
57
|
+
} from '../utils'
|
|
47
58
|
import { getCurrentNodeProvider } from '../global'
|
|
48
59
|
import * as path from 'path'
|
|
49
60
|
import { EventSubscription, subscribeToEvents } from './events'
|
|
61
|
+
import { ONE_ALPH } from '../constants'
|
|
50
62
|
|
|
51
63
|
export type FieldsSig = node.FieldsSig
|
|
52
64
|
export type EventSig = node.EventSig
|
|
@@ -871,14 +883,23 @@ export class Contract extends Artifact {
|
|
|
871
883
|
}
|
|
872
884
|
}
|
|
873
885
|
|
|
874
|
-
fromApiTestContractResult(
|
|
886
|
+
fromApiTestContractResult(
|
|
887
|
+
methodName: string,
|
|
888
|
+
result: node.TestContractResult,
|
|
889
|
+
txId: string
|
|
890
|
+
): TestContractResult<unknown> {
|
|
891
|
+
const methodIndex = this.functions.findIndex((sig) => sig.name === methodName)
|
|
892
|
+
const returnTypes = this.functions[`${methodIndex}`].returnTypes
|
|
893
|
+
const rawReturn = fromApiArray(result.returns, returnTypes)
|
|
894
|
+
const returns = rawReturn.length === 0 ? null : rawReturn.length === 1 ? rawReturn[0] : rawReturn
|
|
895
|
+
|
|
875
896
|
const addressToCodeHash = new Map<string, string>()
|
|
876
897
|
addressToCodeHash.set(result.address, result.codeHash)
|
|
877
898
|
result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash))
|
|
878
899
|
return {
|
|
879
900
|
contractId: binToHex(contractIdFromAddress(result.address)),
|
|
880
901
|
contractAddress: result.address,
|
|
881
|
-
returns:
|
|
902
|
+
returns: returns,
|
|
882
903
|
gasUsed: result.gasUsed,
|
|
883
904
|
contracts: result.contracts.map((contract) => Contract.fromApiContractState(contract)),
|
|
884
905
|
txOutputs: result.txOutputs.map(fromApiOutput),
|
|
@@ -941,11 +962,17 @@ export class Contract extends Artifact {
|
|
|
941
962
|
}
|
|
942
963
|
}
|
|
943
964
|
|
|
944
|
-
fromApiCallContractResult(
|
|
965
|
+
fromApiCallContractResult(
|
|
966
|
+
result: node.CallContractResult,
|
|
967
|
+
txId: string,
|
|
968
|
+
methodIndex: number
|
|
969
|
+
): CallContractResult<unknown> {
|
|
970
|
+
const returnTypes = this.functions[`${methodIndex}`].returnTypes
|
|
971
|
+
const rawReturn = fromApiArray(result.returns, returnTypes)
|
|
972
|
+
const returns = rawReturn.length === 0 ? null : rawReturn.length === 1 ? rawReturn[0] : rawReturn
|
|
973
|
+
|
|
945
974
|
const addressToCodeHash = new Map<string, string>()
|
|
946
975
|
result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash))
|
|
947
|
-
const functionSig = this.functions[`${methodIndex}`]
|
|
948
|
-
const returns = fromApiArray(result.returns, functionSig.returnTypes)
|
|
949
976
|
return {
|
|
950
977
|
returns: returns,
|
|
951
978
|
gasUsed: result.gasUsed,
|
|
@@ -1180,10 +1207,10 @@ export interface ContractEvent<T extends Fields = Fields> {
|
|
|
1180
1207
|
|
|
1181
1208
|
export type DebugMessage = node.DebugMessage
|
|
1182
1209
|
|
|
1183
|
-
export interface TestContractResult {
|
|
1210
|
+
export interface TestContractResult<R> {
|
|
1184
1211
|
contractId: string
|
|
1185
1212
|
contractAddress: string
|
|
1186
|
-
returns:
|
|
1213
|
+
returns: R
|
|
1187
1214
|
gasUsed: number
|
|
1188
1215
|
contracts: ContractState[]
|
|
1189
1216
|
txOutputs: Output[]
|
|
@@ -1250,13 +1277,16 @@ assertType<
|
|
|
1250
1277
|
>
|
|
1251
1278
|
export type DeployContractResult<T> = SignDeployContractTxResult & { instance: T }
|
|
1252
1279
|
|
|
1253
|
-
export abstract class ContractFactory<
|
|
1280
|
+
export abstract class ContractFactory<I, F extends Fields = Fields> {
|
|
1254
1281
|
readonly contract: Contract
|
|
1282
|
+
|
|
1255
1283
|
constructor(contract: Contract) {
|
|
1256
1284
|
this.contract = contract
|
|
1257
1285
|
}
|
|
1258
1286
|
|
|
1259
|
-
|
|
1287
|
+
abstract at(address: string): I
|
|
1288
|
+
|
|
1289
|
+
async deploy(signer: SignerProvider, deployParams: DeployContractParams<F>): Promise<DeployContractResult<I>> {
|
|
1260
1290
|
const signerParams = await this.contract.txParamsForDeployment(signer, deployParams)
|
|
1261
1291
|
const result = await signer.signAndSubmitDeployContractTx(signerParams)
|
|
1262
1292
|
return {
|
|
@@ -1265,7 +1295,14 @@ export abstract class ContractFactory<T, P extends Fields = Fields> {
|
|
|
1265
1295
|
}
|
|
1266
1296
|
}
|
|
1267
1297
|
|
|
1268
|
-
|
|
1298
|
+
// This is used for testing contract functions
|
|
1299
|
+
stateForTest(initFields: F, asset?: Asset, address?: string): ContractState<F> {
|
|
1300
|
+
const newAsset = {
|
|
1301
|
+
alphAmount: asset?.alphAmount ?? ONE_ALPH,
|
|
1302
|
+
tokens: asset?.tokens
|
|
1303
|
+
}
|
|
1304
|
+
return this.contract.toState(initFields, newAsset, address)
|
|
1305
|
+
}
|
|
1269
1306
|
}
|
|
1270
1307
|
|
|
1271
1308
|
export interface ExecuteScriptParams<P extends Fields = Fields> {
|
|
@@ -1293,8 +1330,8 @@ export interface CallContractParams<T extends Arguments = Arguments> {
|
|
|
1293
1330
|
inputAssets?: node.TestInputAsset[]
|
|
1294
1331
|
}
|
|
1295
1332
|
|
|
1296
|
-
export interface CallContractResult {
|
|
1297
|
-
returns:
|
|
1333
|
+
export interface CallContractResult<R> {
|
|
1334
|
+
returns: R
|
|
1298
1335
|
gasUsed: number
|
|
1299
1336
|
contracts: ContractState[]
|
|
1300
1337
|
txInputs: string[]
|
|
@@ -1336,11 +1373,11 @@ export function decodeContractDestroyedEvent(
|
|
|
1336
1373
|
}
|
|
1337
1374
|
}
|
|
1338
1375
|
|
|
1339
|
-
export function subscribeEventsFromContract<T extends Fields
|
|
1340
|
-
options: SubscribeOptions<
|
|
1376
|
+
export function subscribeEventsFromContract<T extends Fields, M extends ContractEvent<T>>(
|
|
1377
|
+
options: SubscribeOptions<M>,
|
|
1341
1378
|
address: string,
|
|
1342
1379
|
eventIndex: number,
|
|
1343
|
-
decodeFunc: (event: node.ContractEvent) =>
|
|
1380
|
+
decodeFunc: (event: node.ContractEvent) => M,
|
|
1344
1381
|
fromCount?: number
|
|
1345
1382
|
): EventSubscription {
|
|
1346
1383
|
const messageCallback = (event: node.ContractEvent): Promise<void> => {
|
|
@@ -1351,7 +1388,7 @@ export function subscribeEventsFromContract<T extends Fields>(
|
|
|
1351
1388
|
}
|
|
1352
1389
|
|
|
1353
1390
|
const errorCallback = (err: any, subscription: Subscription<node.ContractEvent>): Promise<void> => {
|
|
1354
|
-
return options.errorCallback(err, subscription as unknown as Subscription<
|
|
1391
|
+
return options.errorCallback(err, subscription as unknown as Subscription<M>)
|
|
1355
1392
|
}
|
|
1356
1393
|
const opt: SubscribeOptions<node.ContractEvent> = {
|
|
1357
1394
|
pollingInterval: options.pollingInterval,
|
|
@@ -1360,3 +1397,187 @@ export function subscribeEventsFromContract<T extends Fields>(
|
|
|
1360
1397
|
}
|
|
1361
1398
|
return subscribeToEvents(opt, address, fromCount)
|
|
1362
1399
|
}
|
|
1400
|
+
|
|
1401
|
+
export async function testMethod<I, F extends Fields, A extends Arguments, R>(
|
|
1402
|
+
contract: ContractFactory<I, F>,
|
|
1403
|
+
methodName: string,
|
|
1404
|
+
params: Optional<TestContractParams<F, A>, 'testArgs' | 'initialFields'>
|
|
1405
|
+
): Promise<TestContractResult<R>> {
|
|
1406
|
+
const txId = params?.txId ?? randomTxId()
|
|
1407
|
+
const apiParams = contract.contract.toApiTestContractParams(methodName, {
|
|
1408
|
+
...params,
|
|
1409
|
+
txId: txId,
|
|
1410
|
+
initialFields: params.initialFields === undefined ? {} : params.initialFields,
|
|
1411
|
+
testArgs: params.testArgs === undefined ? {} : params.testArgs
|
|
1412
|
+
})
|
|
1413
|
+
const apiResult = await getCurrentNodeProvider().contracts.postContractsTestContract(apiParams)
|
|
1414
|
+
const testResult = contract.contract.fromApiTestContractResult(methodName, apiResult, txId)
|
|
1415
|
+
contract.contract.printDebugMessages(methodName, testResult.debugMessages)
|
|
1416
|
+
return testResult as TestContractResult<R>
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
export abstract class ContractInstance {
|
|
1420
|
+
readonly address: Address
|
|
1421
|
+
readonly contractId: string
|
|
1422
|
+
readonly groupIndex: number
|
|
1423
|
+
|
|
1424
|
+
constructor(address: Address) {
|
|
1425
|
+
this.address = address
|
|
1426
|
+
this.contractId = binToHex(contractIdFromAddress(address))
|
|
1427
|
+
this.groupIndex = groupOfAddress(address)
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
export async function fetchContractState<F extends Fields, I extends ContractInstance>(
|
|
1432
|
+
contract: ContractFactory<I, F>,
|
|
1433
|
+
instance: ContractInstance
|
|
1434
|
+
): Promise<ContractState<F>> {
|
|
1435
|
+
const contractState = await getCurrentNodeProvider().contracts.getContractsAddressState(instance.address, {
|
|
1436
|
+
group: instance.groupIndex
|
|
1437
|
+
})
|
|
1438
|
+
const state = contract.contract.fromApiContractState(contractState)
|
|
1439
|
+
return {
|
|
1440
|
+
...state,
|
|
1441
|
+
fields: state.fields as F
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
export function subscribeContractCreatedEvent(
|
|
1446
|
+
instance: ContractInstance,
|
|
1447
|
+
options: SubscribeOptions<ContractCreatedEvent>,
|
|
1448
|
+
fromCount?: number
|
|
1449
|
+
): EventSubscription {
|
|
1450
|
+
return subscribeEventsFromContract(
|
|
1451
|
+
options,
|
|
1452
|
+
instance.address,
|
|
1453
|
+
Contract.ContractCreatedEventIndex,
|
|
1454
|
+
(event) => {
|
|
1455
|
+
return {
|
|
1456
|
+
...decodeContractCreatedEvent(event),
|
|
1457
|
+
contractAddress: instance.address
|
|
1458
|
+
}
|
|
1459
|
+
},
|
|
1460
|
+
fromCount
|
|
1461
|
+
)
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
export function subscribeContractDestroyedEvent(
|
|
1465
|
+
instance: ContractInstance,
|
|
1466
|
+
options: SubscribeOptions<ContractDestroyedEvent>,
|
|
1467
|
+
fromCount?: number
|
|
1468
|
+
): EventSubscription {
|
|
1469
|
+
return subscribeEventsFromContract(
|
|
1470
|
+
options,
|
|
1471
|
+
instance.address,
|
|
1472
|
+
Contract.ContractDestroyedEventIndex,
|
|
1473
|
+
(event) => {
|
|
1474
|
+
return {
|
|
1475
|
+
...decodeContractDestroyedEvent(event),
|
|
1476
|
+
contractAddress: instance.address
|
|
1477
|
+
}
|
|
1478
|
+
},
|
|
1479
|
+
fromCount
|
|
1480
|
+
)
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
export function decodeEvent<F extends Fields, M extends ContractEvent<F>>(
|
|
1484
|
+
contract: Contract,
|
|
1485
|
+
instance: ContractInstance,
|
|
1486
|
+
event: node.ContractEvent,
|
|
1487
|
+
targetEventIndex: number
|
|
1488
|
+
): M {
|
|
1489
|
+
if (
|
|
1490
|
+
event.eventIndex !== targetEventIndex &&
|
|
1491
|
+
!(targetEventIndex >= 0 && targetEventIndex < contract.eventsSig.length)
|
|
1492
|
+
) {
|
|
1493
|
+
throw new Error('Invalid event index: ' + event.eventIndex + ', expected: ' + targetEventIndex)
|
|
1494
|
+
}
|
|
1495
|
+
const eventSig = contract.eventsSig[`${targetEventIndex}`]
|
|
1496
|
+
const fieldNames = eventSig.fieldNames
|
|
1497
|
+
const fieldTypes = eventSig.fieldTypes
|
|
1498
|
+
const fields = fromApiVals(event.fields, fieldNames, fieldTypes)
|
|
1499
|
+
return {
|
|
1500
|
+
contractAddress: instance.address,
|
|
1501
|
+
blockHash: event.blockHash,
|
|
1502
|
+
txId: event.txId,
|
|
1503
|
+
eventIndex: event.eventIndex,
|
|
1504
|
+
name: eventSig.name,
|
|
1505
|
+
fields: fields
|
|
1506
|
+
} as M
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
export function subscribeContractEvent<F extends Fields, M extends ContractEvent<F>>(
|
|
1510
|
+
contract: Contract,
|
|
1511
|
+
instance: ContractInstance,
|
|
1512
|
+
options: SubscribeOptions<M>,
|
|
1513
|
+
eventName: string,
|
|
1514
|
+
fromCount?: number
|
|
1515
|
+
): EventSubscription {
|
|
1516
|
+
const eventIndex = contract.eventsSig.findIndex((sig) => sig.name === eventName)
|
|
1517
|
+
return subscribeEventsFromContract<F, M>(
|
|
1518
|
+
options,
|
|
1519
|
+
instance.address,
|
|
1520
|
+
eventIndex,
|
|
1521
|
+
(event) => decodeEvent(contract, instance, event, eventIndex),
|
|
1522
|
+
fromCount
|
|
1523
|
+
)
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
export function subscribeAllEvents(
|
|
1527
|
+
contract: Contract,
|
|
1528
|
+
instance: ContractInstance,
|
|
1529
|
+
options: SubscribeOptions<ContractEvent<any>>,
|
|
1530
|
+
fromCount?: number
|
|
1531
|
+
): EventSubscription {
|
|
1532
|
+
const messageCallback = (event: node.ContractEvent): Promise<void> => {
|
|
1533
|
+
switch (event.eventIndex) {
|
|
1534
|
+
case Contract.ContractCreatedEventIndex: {
|
|
1535
|
+
return options.messageCallback({
|
|
1536
|
+
...decodeContractCreatedEvent(event),
|
|
1537
|
+
contractAddress: instance.address
|
|
1538
|
+
})
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
case Contract.ContractDestroyedEventIndex: {
|
|
1542
|
+
return options.messageCallback({
|
|
1543
|
+
...decodeContractDestroyedEvent(event),
|
|
1544
|
+
contractAddress: instance.address
|
|
1545
|
+
})
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
default:
|
|
1549
|
+
return options.messageCallback({
|
|
1550
|
+
...decodeEvent(contract, instance, event, event.eventIndex),
|
|
1551
|
+
contractAddress: instance.address
|
|
1552
|
+
})
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
const errorCallback = (err: any, subscription: Subscription<node.ContractEvent>): Promise<void> => {
|
|
1556
|
+
return options.errorCallback(err, subscription as unknown as Subscription<ContractEvent<any>>)
|
|
1557
|
+
}
|
|
1558
|
+
const opt: SubscribeOptions<node.ContractEvent> = {
|
|
1559
|
+
pollingInterval: options.pollingInterval,
|
|
1560
|
+
messageCallback: messageCallback,
|
|
1561
|
+
errorCallback: errorCallback
|
|
1562
|
+
}
|
|
1563
|
+
return subscribeToEvents(opt, instance.address, fromCount)
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
export async function callMethod<I, F extends Fields, A extends Arguments, R>(
|
|
1567
|
+
contract: ContractFactory<I, F>,
|
|
1568
|
+
instance: ContractInstance,
|
|
1569
|
+
methodName: string,
|
|
1570
|
+
params: Optional<CallContractParams<A>, 'args'>
|
|
1571
|
+
): Promise<CallContractResult<R>> {
|
|
1572
|
+
const methodIndex = contract.contract.getMethodIndex(methodName)
|
|
1573
|
+
const txId = params?.txId ?? randomTxId()
|
|
1574
|
+
const callParams = contract.contract.toApiCallContract(
|
|
1575
|
+
{ ...params, txId: txId, args: params.args === undefined ? {} : params.args },
|
|
1576
|
+
instance.groupIndex,
|
|
1577
|
+
instance.address,
|
|
1578
|
+
methodIndex
|
|
1579
|
+
)
|
|
1580
|
+
const result = await getCurrentNodeProvider().contracts.postContractsCallContract(callParams)
|
|
1581
|
+
const callResult = contract.contract.fromApiCallContractResult(result, txId, methodIndex)
|
|
1582
|
+
return callResult as CallContractResult<R>
|
|
1583
|
+
}
|
package/src/utils/utils.ts
CHANGED
|
@@ -219,3 +219,4 @@ type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1
|
|
|
219
219
|
export type Eq<X, Y> = _Eq<{ [P in keyof X]: X[P] }, { [P in keyof Y]: Y[P] }>
|
|
220
220
|
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
|
|
221
221
|
export function assertType<T extends true>(): void {}
|
|
222
|
+
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
|