@alephium/web3 0.4.0 → 0.5.0-rc.1
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/api/api-alephium.d.ts +5 -3
- package/dist/src/api/api-alephium.js +1 -1
- package/dist/src/api/types.d.ts +1 -0
- package/dist/src/api/types.js +9 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.js +2 -1
- package/dist/src/contract/contract.d.ts +90 -49
- package/dist/src/contract/contract.js +297 -77
- package/dist/src/contract/ralph.js +12 -3
- package/dist/src/signer/tx-builder.js +2 -2
- package/dist/src/signer/types.d.ts +2 -4
- package/dist/src/utils/utils.d.ts +1 -0
- package/dist/src/utils/utils.js +3 -1
- package/package.json +3 -3
- package/src/api/api-alephium.ts +5 -3
- package/src/api/types.ts +8 -0
- package/src/constants.ts +1 -0
- package/src/contract/contract.ts +472 -143
- package/src/contract/ralph.ts +13 -3
- package/src/signer/tx-builder.ts +2 -2
- package/src/signer/types.ts +14 -6
- package/src/utils/utils.ts +4 -1
package/src/contract/contract.ts
CHANGED
|
@@ -33,26 +33,39 @@ import {
|
|
|
33
33
|
Token,
|
|
34
34
|
Val,
|
|
35
35
|
fromApiTokens,
|
|
36
|
-
fromApiVals
|
|
36
|
+
fromApiVals,
|
|
37
|
+
typeLength
|
|
37
38
|
} from '../api'
|
|
38
39
|
import {
|
|
39
40
|
SignDeployContractTxParams,
|
|
41
|
+
SignDeployContractTxResult,
|
|
40
42
|
SignExecuteScriptTxParams,
|
|
41
43
|
SignerProvider,
|
|
42
|
-
|
|
43
|
-
SignDeployContractTxResult
|
|
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
|
-
import { web3 } from '..'
|
|
49
59
|
import * as path from 'path'
|
|
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
|
|
53
65
|
export type FunctionSig = node.FunctionSig
|
|
54
66
|
export type Fields = NamedVals
|
|
55
67
|
export type Arguments = NamedVals
|
|
68
|
+
export type HexString = string
|
|
56
69
|
|
|
57
70
|
enum SourceKind {
|
|
58
71
|
Contract = 0,
|
|
@@ -354,7 +367,7 @@ export class Project {
|
|
|
354
367
|
return script.artifact
|
|
355
368
|
}
|
|
356
369
|
|
|
357
|
-
private async saveArtifactsToFile(): Promise<void> {
|
|
370
|
+
private async saveArtifactsToFile(projectRootDir: string): Promise<void> {
|
|
358
371
|
const artifactsRootDir = this.artifactsRootDir
|
|
359
372
|
const saveToFile = async function (compiled: Compiled<Artifact>): Promise<void> {
|
|
360
373
|
const artifactPath = compiled.sourceInfo.getArtifactPath(artifactsRootDir)
|
|
@@ -366,7 +379,7 @@ export class Project {
|
|
|
366
379
|
}
|
|
367
380
|
this.contracts.forEach((contract) => saveToFile(contract))
|
|
368
381
|
this.scripts.forEach((script) => saveToFile(script))
|
|
369
|
-
await this.projectArtifact.saveToFile(
|
|
382
|
+
await this.projectArtifact.saveToFile(projectRootDir)
|
|
370
383
|
}
|
|
371
384
|
|
|
372
385
|
contractByCodeHash(codeHash: string): Contract {
|
|
@@ -382,6 +395,7 @@ export class Project {
|
|
|
382
395
|
private static async compile(
|
|
383
396
|
provider: NodeProvider,
|
|
384
397
|
sourceInfos: SourceInfo[],
|
|
398
|
+
projectRootDir: string,
|
|
385
399
|
contractsRootDir: string,
|
|
386
400
|
artifactsRootDir: string,
|
|
387
401
|
errorOnWarnings: boolean,
|
|
@@ -414,7 +428,7 @@ export class Project {
|
|
|
414
428
|
errorOnWarnings,
|
|
415
429
|
projectArtifact
|
|
416
430
|
)
|
|
417
|
-
await project.saveArtifactsToFile()
|
|
431
|
+
await project.saveArtifactsToFile(projectRootDir)
|
|
418
432
|
return project
|
|
419
433
|
}
|
|
420
434
|
|
|
@@ -422,6 +436,7 @@ export class Project {
|
|
|
422
436
|
provider: NodeProvider,
|
|
423
437
|
sourceInfos: SourceInfo[],
|
|
424
438
|
projectArtifact: ProjectArtifact,
|
|
439
|
+
projectRootDir: string,
|
|
425
440
|
contractsRootDir: string,
|
|
426
441
|
artifactsRootDir: string,
|
|
427
442
|
errorOnWarnings: boolean,
|
|
@@ -460,6 +475,7 @@ export class Project {
|
|
|
460
475
|
return Project.compile(
|
|
461
476
|
provider,
|
|
462
477
|
sourceInfos,
|
|
478
|
+
projectRootDir,
|
|
463
479
|
contractsRootDir,
|
|
464
480
|
artifactsRootDir,
|
|
465
481
|
errorOnWarnings,
|
|
@@ -590,12 +606,13 @@ export class Project {
|
|
|
590
606
|
const provider = getCurrentNodeProvider()
|
|
591
607
|
const sourceFiles = await Project.loadSourceFiles(projectRootDir, contractsRootDir)
|
|
592
608
|
const { errorOnWarnings, ...nodeCompilerOptions } = { ...DEFAULT_COMPILER_OPTIONS, ...compilerOptionsPartial }
|
|
593
|
-
const projectArtifact = await ProjectArtifact.from(
|
|
609
|
+
const projectArtifact = await ProjectArtifact.from(projectRootDir)
|
|
594
610
|
if (typeof projectArtifact === 'undefined' || projectArtifact.needToReCompile(nodeCompilerOptions, sourceFiles)) {
|
|
595
611
|
console.log(`Compiling contracts in folder "${contractsRootDir}"`)
|
|
596
612
|
Project.currentProject = await Project.compile(
|
|
597
613
|
provider,
|
|
598
614
|
sourceFiles,
|
|
615
|
+
projectRootDir,
|
|
599
616
|
contractsRootDir,
|
|
600
617
|
artifactsRootDir,
|
|
601
618
|
errorOnWarnings,
|
|
@@ -607,6 +624,7 @@ export class Project {
|
|
|
607
624
|
provider,
|
|
608
625
|
sourceFiles,
|
|
609
626
|
projectArtifact,
|
|
627
|
+
projectRootDir,
|
|
610
628
|
contractsRootDir,
|
|
611
629
|
artifactsRootDir,
|
|
612
630
|
errorOnWarnings,
|
|
@@ -722,13 +740,6 @@ export class Contract extends Artifact {
|
|
|
722
740
|
return Contract.fromJson(artifact, bytecodeDebugPatch, codeHashDebug)
|
|
723
741
|
}
|
|
724
742
|
|
|
725
|
-
async fetchState(address: string, group: number): Promise<ContractState> {
|
|
726
|
-
const state = await web3.getCurrentNodeProvider().contracts.getContractsAddressState(address, {
|
|
727
|
-
group: group
|
|
728
|
-
})
|
|
729
|
-
return this.fromApiContractState(state)
|
|
730
|
-
}
|
|
731
|
-
|
|
732
743
|
override toString(): string {
|
|
733
744
|
const object = {
|
|
734
745
|
version: this.version,
|
|
@@ -742,7 +753,7 @@ export class Contract extends Artifact {
|
|
|
742
753
|
return JSON.stringify(object, null, 2)
|
|
743
754
|
}
|
|
744
755
|
|
|
745
|
-
toState(fields:
|
|
756
|
+
toState<T extends Fields>(fields: T, asset: Asset, address?: string): ContractState<T> {
|
|
746
757
|
const addressDef = typeof address !== 'undefined' ? address : Contract.randomAddress()
|
|
747
758
|
return {
|
|
748
759
|
address: addressDef,
|
|
@@ -763,53 +774,13 @@ export class Contract extends Artifact {
|
|
|
763
774
|
return bs58.encode(bytes)
|
|
764
775
|
}
|
|
765
776
|
|
|
766
|
-
|
|
777
|
+
printDebugMessages(funcName: string, messages: DebugMessage[]) {
|
|
767
778
|
if (messages.length != 0) {
|
|
768
779
|
console.log(`Testing ${this.name}.${funcName}:`)
|
|
769
780
|
messages.forEach((m) => console.log(`Debug - ${m.contractAddress} - ${m.message}`))
|
|
770
781
|
}
|
|
771
782
|
}
|
|
772
783
|
|
|
773
|
-
private async _test(
|
|
774
|
-
funcName: string,
|
|
775
|
-
params: TestContractParams,
|
|
776
|
-
expectPublic: boolean,
|
|
777
|
-
accessType: string,
|
|
778
|
-
printDebugMessages: boolean
|
|
779
|
-
): Promise<TestContractResult> {
|
|
780
|
-
const apiParams: node.TestContract = this.toTestContract(funcName, params)
|
|
781
|
-
const apiResult = await web3.getCurrentNodeProvider().contracts.postContractsTestContract(apiParams)
|
|
782
|
-
|
|
783
|
-
const methodIndex =
|
|
784
|
-
typeof params.testMethodIndex !== 'undefined' ? params.testMethodIndex : this.getMethodIndex(funcName)
|
|
785
|
-
const isPublic = this.functions[`${methodIndex}`].isPublic
|
|
786
|
-
if (printDebugMessages) {
|
|
787
|
-
this._printDebugMessages(funcName, apiResult.debugMessages)
|
|
788
|
-
}
|
|
789
|
-
if (isPublic === expectPublic) {
|
|
790
|
-
const result = await this.fromTestContractResult(methodIndex, apiResult)
|
|
791
|
-
return result
|
|
792
|
-
} else {
|
|
793
|
-
throw new Error(`The test method ${funcName} is not ${accessType}`)
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
async testPublicMethod(
|
|
798
|
-
funcName: string,
|
|
799
|
-
params: TestContractParams,
|
|
800
|
-
printDebugMessages = true
|
|
801
|
-
): Promise<TestContractResult> {
|
|
802
|
-
return this._test(funcName, params, true, 'public', printDebugMessages)
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
async testPrivateMethod(
|
|
806
|
-
funcName: string,
|
|
807
|
-
params: TestContractParams,
|
|
808
|
-
printDebugMessages = true
|
|
809
|
-
): Promise<TestContractResult> {
|
|
810
|
-
return this._test(funcName, params, false, 'private', printDebugMessages)
|
|
811
|
-
}
|
|
812
|
-
|
|
813
784
|
toApiFields(fields?: Fields): node.Val[] {
|
|
814
785
|
if (typeof fields === 'undefined') {
|
|
815
786
|
return []
|
|
@@ -839,12 +810,17 @@ export class Contract extends Artifact {
|
|
|
839
810
|
return typeof states != 'undefined' ? states.map((state) => toApiContractState(state)) : undefined
|
|
840
811
|
}
|
|
841
812
|
|
|
842
|
-
|
|
813
|
+
toApiTestContractParams(funcName: string, params: TestContractParams): node.TestContract {
|
|
814
|
+
const immFields =
|
|
815
|
+
params.initialFields === undefined ? [] : extractFields(params.initialFields, this.fieldsSig, false)
|
|
816
|
+
const mutFields =
|
|
817
|
+
params.initialFields === undefined ? [] : extractFields(params.initialFields, this.fieldsSig, true)
|
|
843
818
|
return {
|
|
844
819
|
group: params.group,
|
|
845
820
|
address: params.address,
|
|
846
821
|
bytecode: this.bytecodeDebug,
|
|
847
|
-
|
|
822
|
+
initialImmFields: immFields,
|
|
823
|
+
initialMutFields: mutFields,
|
|
848
824
|
initialAsset: typeof params.initialAsset !== 'undefined' ? toApiAsset(params.initialAsset) : undefined,
|
|
849
825
|
methodIndex: this.getMethodIndex(funcName),
|
|
850
826
|
args: this.toApiArgs(funcName, params.testArgs),
|
|
@@ -853,14 +829,14 @@ export class Contract extends Artifact {
|
|
|
853
829
|
}
|
|
854
830
|
}
|
|
855
831
|
|
|
856
|
-
fromApiContractState(state: node.ContractState): ContractState {
|
|
832
|
+
fromApiContractState(state: node.ContractState): ContractState<Fields> {
|
|
857
833
|
return {
|
|
858
834
|
address: state.address,
|
|
859
835
|
contractId: binToHex(contractIdFromAddress(state.address)),
|
|
860
836
|
bytecode: state.bytecode,
|
|
861
837
|
initialStateHash: state.initialStateHash,
|
|
862
838
|
codeHash: state.codeHash,
|
|
863
|
-
fields: fromApiFields(state.
|
|
839
|
+
fields: fromApiFields(state.immFields, state.mutFields, this.fieldsSig),
|
|
864
840
|
fieldsSig: this.fieldsSig,
|
|
865
841
|
asset: fromApiAsset(state.asset)
|
|
866
842
|
}
|
|
@@ -871,24 +847,26 @@ export class Contract extends Artifact {
|
|
|
871
847
|
return contract.fromApiContractState(state)
|
|
872
848
|
}
|
|
873
849
|
|
|
850
|
+
static ContractCreatedEventIndex = -1
|
|
874
851
|
static ContractCreatedEvent: EventSig = {
|
|
875
852
|
name: 'ContractCreated',
|
|
876
853
|
fieldNames: ['address'],
|
|
877
854
|
fieldTypes: ['Address']
|
|
878
855
|
}
|
|
879
856
|
|
|
857
|
+
static ContractDestroyedEventIndex = -2
|
|
880
858
|
static ContractDestroyedEvent: EventSig = {
|
|
881
859
|
name: 'ContractDestroyed',
|
|
882
860
|
fieldNames: ['address'],
|
|
883
861
|
fieldTypes: ['Address']
|
|
884
862
|
}
|
|
885
863
|
|
|
886
|
-
static fromApiEvent(event: node.ContractEventByTxId, codeHash: string | undefined):
|
|
864
|
+
static fromApiEvent(event: node.ContractEventByTxId, codeHash: string | undefined, txId: string): ContractEvent {
|
|
887
865
|
let eventSig: EventSig
|
|
888
866
|
|
|
889
|
-
if (event.eventIndex ==
|
|
867
|
+
if (event.eventIndex == Contract.ContractCreatedEventIndex) {
|
|
890
868
|
eventSig = this.ContractCreatedEvent
|
|
891
|
-
} else if (event.eventIndex ==
|
|
869
|
+
} else if (event.eventIndex == Contract.ContractDestroyedEventIndex) {
|
|
892
870
|
eventSig = this.ContractDestroyedEvent
|
|
893
871
|
} else {
|
|
894
872
|
const contract = Project.currentProject.contractByCodeHash(codeHash!)
|
|
@@ -896,65 +874,114 @@ export class Contract extends Artifact {
|
|
|
896
874
|
}
|
|
897
875
|
|
|
898
876
|
return {
|
|
877
|
+
txId: txId,
|
|
899
878
|
blockHash: event.blockHash,
|
|
900
879
|
contractAddress: event.contractAddress,
|
|
901
880
|
name: eventSig.name,
|
|
881
|
+
eventIndex: event.eventIndex,
|
|
902
882
|
fields: fromApiEventFields(event.fields, eventSig)
|
|
903
883
|
}
|
|
904
884
|
}
|
|
905
885
|
|
|
906
|
-
|
|
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
|
+
|
|
907
896
|
const addressToCodeHash = new Map<string, string>()
|
|
908
897
|
addressToCodeHash.set(result.address, result.codeHash)
|
|
909
898
|
result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash))
|
|
910
899
|
return {
|
|
911
900
|
contractId: binToHex(contractIdFromAddress(result.address)),
|
|
912
901
|
contractAddress: result.address,
|
|
913
|
-
returns:
|
|
902
|
+
returns: returns,
|
|
914
903
|
gasUsed: result.gasUsed,
|
|
915
904
|
contracts: result.contracts.map((contract) => Contract.fromApiContractState(contract)),
|
|
916
905
|
txOutputs: result.txOutputs.map(fromApiOutput),
|
|
917
|
-
events: result.events
|
|
918
|
-
const contractAddress = event.contractAddress
|
|
919
|
-
const codeHash = addressToCodeHash.get(contractAddress)
|
|
920
|
-
if (typeof codeHash !== 'undefined' || event.eventIndex < 0) {
|
|
921
|
-
return Contract.fromApiEvent(event, codeHash)
|
|
922
|
-
} else {
|
|
923
|
-
throw Error(`Cannot find codeHash for the contract address: ${contractAddress}`)
|
|
924
|
-
}
|
|
925
|
-
}),
|
|
906
|
+
events: Contract.fromApiEvents(result.events, addressToCodeHash, txId),
|
|
926
907
|
debugMessages: result.debugMessages
|
|
927
908
|
}
|
|
928
909
|
}
|
|
929
910
|
|
|
930
|
-
async txParamsForDeployment(
|
|
911
|
+
async txParamsForDeployment<P extends Fields>(
|
|
931
912
|
signer: SignerProvider,
|
|
932
|
-
params:
|
|
913
|
+
params: DeployContractParams<P>
|
|
933
914
|
): Promise<SignDeployContractTxParams> {
|
|
934
|
-
const bytecode = this.buildByteCodeToDeploy(params.initialFields
|
|
915
|
+
const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {})
|
|
935
916
|
const signerParams: SignDeployContractTxParams = {
|
|
936
917
|
signerAddress: await signer.getSelectedAddress(),
|
|
937
918
|
bytecode: bytecode,
|
|
938
|
-
initialAttoAlphAmount: params
|
|
939
|
-
issueTokenAmount: params
|
|
940
|
-
initialTokenAmounts: params
|
|
941
|
-
gasAmount: params
|
|
942
|
-
gasPrice: params
|
|
919
|
+
initialAttoAlphAmount: params?.initialAttoAlphAmount,
|
|
920
|
+
issueTokenAmount: params?.issueTokenAmount,
|
|
921
|
+
initialTokenAmounts: params?.initialTokenAmounts,
|
|
922
|
+
gasAmount: params?.gasAmount,
|
|
923
|
+
gasPrice: params?.gasPrice
|
|
943
924
|
}
|
|
944
925
|
return signerParams
|
|
945
926
|
}
|
|
946
927
|
|
|
947
|
-
async deploy(
|
|
948
|
-
signer: SignerProvider,
|
|
949
|
-
params: Omit<BuildDeployContractTx, 'signerAddress'>
|
|
950
|
-
): Promise<SignDeployContractTxResult> {
|
|
951
|
-
const signerParams = await this.txParamsForDeployment(signer, params)
|
|
952
|
-
return signer.signAndSubmitDeployContractTx(signerParams)
|
|
953
|
-
}
|
|
954
|
-
|
|
955
928
|
buildByteCodeToDeploy(initialFields: Fields): string {
|
|
956
929
|
return ralph.buildContractByteCode(this.bytecode, initialFields, this.fieldsSig)
|
|
957
930
|
}
|
|
931
|
+
|
|
932
|
+
static fromApiEvents(
|
|
933
|
+
events: node.ContractEventByTxId[],
|
|
934
|
+
addressToCodeHash: Map<string, string>,
|
|
935
|
+
txId: string
|
|
936
|
+
): ContractEvent[] {
|
|
937
|
+
return events.map((event) => {
|
|
938
|
+
const contractAddress = event.contractAddress
|
|
939
|
+
const codeHash = addressToCodeHash.get(contractAddress)
|
|
940
|
+
if (typeof codeHash !== 'undefined' || event.eventIndex < 0) {
|
|
941
|
+
return Contract.fromApiEvent(event, codeHash, txId)
|
|
942
|
+
} else {
|
|
943
|
+
throw Error(`Cannot find codeHash for the contract address: ${contractAddress}`)
|
|
944
|
+
}
|
|
945
|
+
})
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
toApiCallContract<T extends Arguments>(
|
|
949
|
+
params: CallContractParams<T>,
|
|
950
|
+
groupIndex: number,
|
|
951
|
+
contractAddress: string,
|
|
952
|
+
methodIndex: number
|
|
953
|
+
): node.CallContract {
|
|
954
|
+
const functionSig = this.functions[`${methodIndex}`]
|
|
955
|
+
const args = toApiVals(params.args ?? {}, functionSig.paramNames, functionSig.paramTypes)
|
|
956
|
+
return {
|
|
957
|
+
...params,
|
|
958
|
+
group: groupIndex,
|
|
959
|
+
address: contractAddress,
|
|
960
|
+
methodIndex: methodIndex,
|
|
961
|
+
args: args
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
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
|
+
|
|
974
|
+
const addressToCodeHash = new Map<string, string>()
|
|
975
|
+
result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash))
|
|
976
|
+
return {
|
|
977
|
+
returns: returns,
|
|
978
|
+
gasUsed: result.gasUsed,
|
|
979
|
+
contracts: result.contracts.map((state) => Contract.fromApiContractState(state)),
|
|
980
|
+
txInputs: result.txInputs,
|
|
981
|
+
txOutputs: result.txOutputs.map((output) => fromApiOutput(output)),
|
|
982
|
+
events: Contract.fromApiEvents(result.events, addressToCodeHash, txId)
|
|
983
|
+
}
|
|
984
|
+
}
|
|
958
985
|
}
|
|
959
986
|
|
|
960
987
|
export class Script extends Artifact {
|
|
@@ -1025,13 +1052,13 @@ export class Script extends Artifact {
|
|
|
1025
1052
|
return JSON.stringify(object, null, 2)
|
|
1026
1053
|
}
|
|
1027
1054
|
|
|
1028
|
-
async txParamsForExecution(
|
|
1055
|
+
async txParamsForExecution<P extends Fields>(
|
|
1029
1056
|
signer: SignerProvider,
|
|
1030
|
-
params:
|
|
1057
|
+
params: ExecuteScriptParams<P>
|
|
1031
1058
|
): Promise<SignExecuteScriptTxParams> {
|
|
1032
1059
|
const signerParams: SignExecuteScriptTxParams = {
|
|
1033
1060
|
signerAddress: await signer.getSelectedAddress(),
|
|
1034
|
-
bytecode: this.buildByteCodeToDeploy(params.initialFields
|
|
1061
|
+
bytecode: this.buildByteCodeToDeploy(params.initialFields ?? {}),
|
|
1035
1062
|
attoAlphAmount: params.attoAlphAmount,
|
|
1036
1063
|
tokens: params.tokens,
|
|
1037
1064
|
gasAmount: params.gasAmount,
|
|
@@ -1040,20 +1067,27 @@ export class Script extends Artifact {
|
|
|
1040
1067
|
return signerParams
|
|
1041
1068
|
}
|
|
1042
1069
|
|
|
1043
|
-
async execute(
|
|
1044
|
-
signer: SignerProvider,
|
|
1045
|
-
params: Omit<BuildExecuteScriptTx, 'signerAddress'>
|
|
1046
|
-
): Promise<SignExecuteScriptTxResult> {
|
|
1047
|
-
const signerParams = await this.txParamsForExecution(signer, params)
|
|
1048
|
-
return await signer.signAndSubmitExecuteScriptTx(signerParams)
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
1070
|
buildByteCodeToDeploy(initialFields: Fields): string {
|
|
1052
1071
|
return ralph.buildScriptByteCode(this.bytecodeTemplate, initialFields, this.fieldsSig)
|
|
1053
1072
|
}
|
|
1054
1073
|
}
|
|
1055
1074
|
|
|
1056
|
-
function fromApiFields(
|
|
1075
|
+
function fromApiFields(immFields: node.Val[], mutFields: node.Val[], fieldsSig: node.FieldsSig): Fields {
|
|
1076
|
+
const vals: node.Val[] = []
|
|
1077
|
+
let immIndex = 0
|
|
1078
|
+
let mutIndex = 0
|
|
1079
|
+
const isMutable = fieldsSig.types.flatMap((tpe, index) =>
|
|
1080
|
+
Array(typeLength(tpe)).fill(fieldsSig.isMutable[`${index}`])
|
|
1081
|
+
)
|
|
1082
|
+
isMutable.forEach((mutable) => {
|
|
1083
|
+
if (mutable) {
|
|
1084
|
+
vals.push(mutFields[`${mutIndex}`])
|
|
1085
|
+
mutIndex += 1
|
|
1086
|
+
} else {
|
|
1087
|
+
vals.push(immFields[`${immIndex}`])
|
|
1088
|
+
immIndex += 1
|
|
1089
|
+
}
|
|
1090
|
+
})
|
|
1057
1091
|
return fromApiVals(vals, fieldsSig.names, fieldsSig.types)
|
|
1058
1092
|
}
|
|
1059
1093
|
|
|
@@ -1085,13 +1119,13 @@ export interface InputAsset {
|
|
|
1085
1119
|
asset: Asset
|
|
1086
1120
|
}
|
|
1087
1121
|
|
|
1088
|
-
export interface ContractState {
|
|
1122
|
+
export interface ContractState<T extends Fields = Fields> {
|
|
1089
1123
|
address: string
|
|
1090
1124
|
contractId: string
|
|
1091
1125
|
bytecode: string
|
|
1092
1126
|
initialStateHash?: string
|
|
1093
1127
|
codeHash: string
|
|
1094
|
-
fields:
|
|
1128
|
+
fields: T
|
|
1095
1129
|
fieldsSig: FieldsSig
|
|
1096
1130
|
asset: Asset
|
|
1097
1131
|
}
|
|
@@ -1104,13 +1138,24 @@ function getVal(vals: NamedVals, name: string): Val {
|
|
|
1104
1138
|
}
|
|
1105
1139
|
}
|
|
1106
1140
|
|
|
1141
|
+
function extractFields(fields: NamedVals, fieldsSig: FieldsSig, mutable: boolean) {
|
|
1142
|
+
const fieldIndexes = fieldsSig.names
|
|
1143
|
+
.map((_, index) => index)
|
|
1144
|
+
.filter((index) => fieldsSig.isMutable[`${index}`] === mutable)
|
|
1145
|
+
const fieldNames = fieldIndexes.map((index) => fieldsSig.names[`${index}`])
|
|
1146
|
+
const fieldTypes = fieldIndexes.map((index) => fieldsSig.types[`${index}`])
|
|
1147
|
+
return toApiVals(fields, fieldNames, fieldTypes)
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1107
1150
|
function toApiContractState(state: ContractState): node.ContractState {
|
|
1151
|
+
const stateFields = state.fields ?? {}
|
|
1108
1152
|
return {
|
|
1109
1153
|
address: state.address,
|
|
1110
1154
|
bytecode: state.bytecode,
|
|
1111
1155
|
codeHash: state.codeHash,
|
|
1112
1156
|
initialStateHash: state.initialStateHash,
|
|
1113
|
-
|
|
1157
|
+
immFields: extractFields(stateFields, state.fieldsSig, false),
|
|
1158
|
+
mutFields: extractFields(stateFields, state.fieldsSig, true),
|
|
1114
1159
|
asset: toApiAsset(state.asset)
|
|
1115
1160
|
}
|
|
1116
1161
|
}
|
|
@@ -1123,7 +1168,7 @@ function toApiArgs(args: Arguments, funcSig: FunctionSig): node.Val[] {
|
|
|
1123
1168
|
return toApiVals(args, funcSig.paramNames, funcSig.paramTypes)
|
|
1124
1169
|
}
|
|
1125
1170
|
|
|
1126
|
-
function toApiVals(fields: Fields, names: string[], types: string[]): node.Val[] {
|
|
1171
|
+
export function toApiVals(fields: Fields, names: string[], types: string[]): node.Val[] {
|
|
1127
1172
|
return names.map((name, index) => {
|
|
1128
1173
|
const val = getVal(fields, name)
|
|
1129
1174
|
const tpe = types[`${index}`]
|
|
@@ -1139,41 +1184,37 @@ function toApiInputAssets(inputAssets?: InputAsset[]): node.TestInputAsset[] | u
|
|
|
1139
1184
|
return typeof inputAssets !== 'undefined' ? inputAssets.map(toApiInputAsset) : undefined
|
|
1140
1185
|
}
|
|
1141
1186
|
|
|
1142
|
-
export interface TestContractParams {
|
|
1187
|
+
export interface TestContractParams<F extends Fields = Fields, A extends Arguments = Arguments> {
|
|
1143
1188
|
group?: number // default 0
|
|
1144
1189
|
address?: string
|
|
1145
|
-
|
|
1190
|
+
blockHash?: string
|
|
1191
|
+
txId?: string
|
|
1192
|
+
initialFields: F
|
|
1146
1193
|
initialAsset?: Asset // default 1 ALPH
|
|
1147
|
-
|
|
1148
|
-
testArgs?: Arguments // default no arguments
|
|
1194
|
+
testArgs: A
|
|
1149
1195
|
existingContracts?: ContractState[] // default no existing contracts
|
|
1150
1196
|
inputAssets?: InputAsset[] // default no input asserts
|
|
1151
1197
|
}
|
|
1152
1198
|
|
|
1153
|
-
export interface ContractEvent {
|
|
1154
|
-
blockHash: string
|
|
1199
|
+
export interface ContractEvent<T extends Fields = Fields> {
|
|
1155
1200
|
txId: string
|
|
1156
|
-
name: string
|
|
1157
|
-
fields: Fields
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
export interface ContractEventByTxId {
|
|
1161
1201
|
blockHash: string
|
|
1162
1202
|
contractAddress: string
|
|
1203
|
+
eventIndex: number
|
|
1163
1204
|
name: string
|
|
1164
|
-
fields:
|
|
1205
|
+
fields: T
|
|
1165
1206
|
}
|
|
1166
1207
|
|
|
1167
1208
|
export type DebugMessage = node.DebugMessage
|
|
1168
1209
|
|
|
1169
|
-
export interface TestContractResult {
|
|
1210
|
+
export interface TestContractResult<R> {
|
|
1170
1211
|
contractId: string
|
|
1171
1212
|
contractAddress: string
|
|
1172
|
-
returns:
|
|
1213
|
+
returns: R
|
|
1173
1214
|
gasUsed: number
|
|
1174
1215
|
contracts: ContractState[]
|
|
1175
1216
|
txOutputs: Output[]
|
|
1176
|
-
events:
|
|
1217
|
+
events: ContractEvent[]
|
|
1177
1218
|
debugMessages: DebugMessage[]
|
|
1178
1219
|
}
|
|
1179
1220
|
export declare type Output = AssetOutput | ContractOutput
|
|
@@ -1214,41 +1255,329 @@ function fromApiOutput(output: node.Output): Output {
|
|
|
1214
1255
|
}
|
|
1215
1256
|
}
|
|
1216
1257
|
|
|
1217
|
-
export
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
txId: string
|
|
1222
|
-
contractAddress: string
|
|
1223
|
-
contractId: string
|
|
1258
|
+
export function randomTxId(): string {
|
|
1259
|
+
const bytes = new Uint8Array(32)
|
|
1260
|
+
crypto.getRandomValues(bytes)
|
|
1261
|
+
return binToHex(bytes)
|
|
1224
1262
|
}
|
|
1225
1263
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
export interface BuildDeployContractTx {
|
|
1229
|
-
signerAddress: string
|
|
1230
|
-
initialFields?: Fields
|
|
1264
|
+
export interface DeployContractParams<P extends Fields = Fields> {
|
|
1265
|
+
initialFields: P
|
|
1231
1266
|
initialAttoAlphAmount?: Number256
|
|
1232
1267
|
initialTokenAmounts?: Token[]
|
|
1233
1268
|
issueTokenAmount?: Number256
|
|
1234
1269
|
gasAmount?: number
|
|
1235
1270
|
gasPrice?: Number256
|
|
1236
1271
|
}
|
|
1237
|
-
assertType<
|
|
1272
|
+
assertType<
|
|
1273
|
+
Eq<
|
|
1274
|
+
Omit<DeployContractParams<undefined>, 'initialFields'>,
|
|
1275
|
+
Omit<SignDeployContractTxParams, 'signerAddress' | 'bytecode'>
|
|
1276
|
+
>
|
|
1277
|
+
>
|
|
1278
|
+
export type DeployContractResult<T> = SignDeployContractTxResult & { instance: T }
|
|
1279
|
+
|
|
1280
|
+
export abstract class ContractFactory<I, F extends Fields = Fields> {
|
|
1281
|
+
readonly contract: Contract
|
|
1282
|
+
|
|
1283
|
+
constructor(contract: Contract) {
|
|
1284
|
+
this.contract = contract
|
|
1285
|
+
}
|
|
1238
1286
|
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1287
|
+
abstract at(address: string): I
|
|
1288
|
+
|
|
1289
|
+
async deploy(signer: SignerProvider, deployParams: DeployContractParams<F>): Promise<DeployContractResult<I>> {
|
|
1290
|
+
const signerParams = await this.contract.txParamsForDeployment(signer, deployParams)
|
|
1291
|
+
const result = await signer.signAndSubmitDeployContractTx(signerParams)
|
|
1292
|
+
return {
|
|
1293
|
+
...result,
|
|
1294
|
+
instance: this.at(result.contractAddress)
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
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
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
export interface ExecuteScriptParams<P extends Fields = Fields> {
|
|
1309
|
+
initialFields: P
|
|
1242
1310
|
attoAlphAmount?: Number256
|
|
1243
1311
|
tokens?: Token[]
|
|
1244
1312
|
gasAmount?: number
|
|
1245
1313
|
gasPrice?: Number256
|
|
1246
1314
|
}
|
|
1247
|
-
assertType<Eq<keyof BuildExecuteScriptTx, keyof BuildTxParams<SignExecuteScriptTxParams>>>()
|
|
1248
1315
|
|
|
1249
|
-
export interface
|
|
1250
|
-
|
|
1251
|
-
toGroup: number
|
|
1316
|
+
export interface ExecuteScriptResult {
|
|
1317
|
+
groupIndex: number
|
|
1252
1318
|
unsignedTx: string
|
|
1253
1319
|
txId: string
|
|
1320
|
+
signature: string
|
|
1321
|
+
gasAmount: number
|
|
1322
|
+
gasPrice: Number256
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
export interface CallContractParams<T extends Arguments = Arguments> {
|
|
1326
|
+
args: T
|
|
1327
|
+
worldStateBlockHash?: string
|
|
1328
|
+
txId?: string
|
|
1329
|
+
existingContracts?: string[]
|
|
1330
|
+
inputAssets?: node.TestInputAsset[]
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
export interface CallContractResult<R> {
|
|
1334
|
+
returns: R
|
|
1335
|
+
gasUsed: number
|
|
1336
|
+
contracts: ContractState[]
|
|
1337
|
+
txInputs: string[]
|
|
1338
|
+
txOutputs: Output[]
|
|
1339
|
+
events: ContractEvent[]
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
export type ContractCreatedEvent = ContractEvent<{ address: HexString }>
|
|
1343
|
+
export type ContractDestroyedEvent = ContractEvent<{ address: HexString }>
|
|
1344
|
+
|
|
1345
|
+
function decodeFields(event: node.ContractEvent, eventSig: EventSig, eventIndex: number): Fields {
|
|
1346
|
+
if (event.eventIndex !== eventIndex) {
|
|
1347
|
+
throw new Error(`Invalid event index: ${event.eventIndex}, expected: ${eventIndex}`)
|
|
1348
|
+
}
|
|
1349
|
+
return fromApiVals(event.fields, eventSig.fieldNames, eventSig.fieldTypes)
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
export function decodeContractCreatedEvent(event: node.ContractEvent): Omit<ContractCreatedEvent, 'contractAddress'> {
|
|
1353
|
+
const fields = decodeFields(event, Contract.ContractCreatedEvent, Contract.ContractCreatedEventIndex)
|
|
1354
|
+
return {
|
|
1355
|
+
blockHash: event.blockHash,
|
|
1356
|
+
txId: event.txId,
|
|
1357
|
+
eventIndex: event.eventIndex,
|
|
1358
|
+
name: Contract.ContractCreatedEvent.name,
|
|
1359
|
+
fields: { address: fields['address'] as HexString }
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
export function decodeContractDestroyedEvent(
|
|
1364
|
+
event: node.ContractEvent
|
|
1365
|
+
): Omit<ContractDestroyedEvent, 'contractAddress'> {
|
|
1366
|
+
const fields = decodeFields(event, Contract.ContractDestroyedEvent, Contract.ContractDestroyedEventIndex)
|
|
1367
|
+
return {
|
|
1368
|
+
blockHash: event.blockHash,
|
|
1369
|
+
txId: event.txId,
|
|
1370
|
+
eventIndex: event.eventIndex,
|
|
1371
|
+
name: Contract.ContractDestroyedEvent.name,
|
|
1372
|
+
fields: { address: fields['address'] as HexString }
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
export function subscribeEventsFromContract<T extends Fields, M extends ContractEvent<T>>(
|
|
1377
|
+
options: SubscribeOptions<M>,
|
|
1378
|
+
address: string,
|
|
1379
|
+
eventIndex: number,
|
|
1380
|
+
decodeFunc: (event: node.ContractEvent) => M,
|
|
1381
|
+
fromCount?: number
|
|
1382
|
+
): EventSubscription {
|
|
1383
|
+
const messageCallback = (event: node.ContractEvent): Promise<void> => {
|
|
1384
|
+
if (event.eventIndex !== eventIndex) {
|
|
1385
|
+
return Promise.resolve()
|
|
1386
|
+
}
|
|
1387
|
+
return options.messageCallback(decodeFunc(event))
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
const errorCallback = (err: any, subscription: Subscription<node.ContractEvent>): Promise<void> => {
|
|
1391
|
+
return options.errorCallback(err, subscription as unknown as Subscription<M>)
|
|
1392
|
+
}
|
|
1393
|
+
const opt: SubscribeOptions<node.ContractEvent> = {
|
|
1394
|
+
pollingInterval: options.pollingInterval,
|
|
1395
|
+
messageCallback: messageCallback,
|
|
1396
|
+
errorCallback: errorCallback
|
|
1397
|
+
}
|
|
1398
|
+
return subscribeToEvents(opt, address, fromCount)
|
|
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>
|
|
1254
1583
|
}
|