@alephium/web3 0.2.0-rc.14 → 0.2.0-rc.16
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 +10 -0
- package/dist/src/api/api-explorer.d.ts +147 -32
- package/dist/src/api/api-explorer.js +133 -1
- package/dist/src/contract/contract.d.ts +24 -16
- package/dist/src/contract/contract.js +43 -22
- package/dist/src/contract/ralph.d.ts +1 -0
- package/dist/src/contract/ralph.js +27 -1
- package/package.json +3 -3
- package/src/api/api-alephium.ts +12 -0
- package/src/api/api-explorer.ts +233 -40
- package/src/contract/contract.ts +94 -27
- package/src/contract/ralph.ts +25 -0
package/src/contract/contract.ts
CHANGED
|
@@ -119,11 +119,13 @@ class Compiled<T extends Artifact> {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
type CodeInfo = { sourceCodeHash: string; bytecodeDebugPatch: string; codeHashDebug: string; warnings: string[] }
|
|
123
|
+
|
|
122
124
|
class ProjectArtifact {
|
|
123
125
|
static readonly artifactFileName = '.project.json'
|
|
124
126
|
|
|
125
127
|
compilerOptionsUsed: node.CompilerOptions
|
|
126
|
-
infos: Map<string,
|
|
128
|
+
infos: Map<string, CodeInfo>
|
|
127
129
|
|
|
128
130
|
static checkCompilerOptionsParameter(compilerOptions: node.CompilerOptions): void {
|
|
129
131
|
if (Object.keys(compilerOptions).length != Object.keys(DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
@@ -136,10 +138,7 @@ class ProjectArtifact {
|
|
|
136
138
|
}
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
constructor(
|
|
140
|
-
compilerOptionsUsed: node.CompilerOptions,
|
|
141
|
-
infos: Map<string, { sourceCodeHash: string; warnings: string[] }>
|
|
142
|
-
) {
|
|
141
|
+
constructor(compilerOptionsUsed: node.CompilerOptions, infos: Map<string, CodeInfo>) {
|
|
143
142
|
ProjectArtifact.checkCompilerOptionsParameter(compilerOptionsUsed)
|
|
144
143
|
this.compilerOptionsUsed = compilerOptionsUsed
|
|
145
144
|
this.infos = infos
|
|
@@ -184,7 +183,7 @@ class ProjectArtifact {
|
|
|
184
183
|
const content = await fsPromises.readFile(filepath)
|
|
185
184
|
const json = JSON.parse(content.toString())
|
|
186
185
|
const compilerOptionsUsed = json.compilerOptionsUsed as node.CompilerOptions
|
|
187
|
-
const files = new Map(Object.entries<
|
|
186
|
+
const files = new Map(Object.entries<CodeInfo>(json.infos))
|
|
188
187
|
return new ProjectArtifact(compilerOptionsUsed, files)
|
|
189
188
|
}
|
|
190
189
|
}
|
|
@@ -221,16 +220,20 @@ export class Project {
|
|
|
221
220
|
scripts: Compiled<Script>[],
|
|
222
221
|
compilerOptions: node.CompilerOptions
|
|
223
222
|
): ProjectArtifact {
|
|
224
|
-
const files: Map<string,
|
|
223
|
+
const files: Map<string, CodeInfo> = new Map()
|
|
225
224
|
contracts.forEach((c) => {
|
|
226
225
|
files.set(c.sourceFile.contractPath, {
|
|
227
226
|
sourceCodeHash: c.sourceFile.sourceCodeHash,
|
|
227
|
+
bytecodeDebugPatch: c.artifact.bytecodeDebugPatch,
|
|
228
|
+
codeHashDebug: c.artifact.codeHashDebug,
|
|
228
229
|
warnings: c.warnings
|
|
229
230
|
})
|
|
230
231
|
})
|
|
231
232
|
scripts.forEach((s) => {
|
|
232
233
|
files.set(s.sourceFile.contractPath, {
|
|
233
234
|
sourceCodeHash: s.sourceFile.sourceCodeHash,
|
|
235
|
+
bytecodeDebugPatch: s.artifact.bytecodeDebugPatch,
|
|
236
|
+
codeHashDebug: '',
|
|
234
237
|
warnings: s.warnings
|
|
235
238
|
})
|
|
236
239
|
})
|
|
@@ -238,6 +241,8 @@ export class Project {
|
|
|
238
241
|
sourceFiles.slice(compiledSize).forEach((c) => {
|
|
239
242
|
files.set(c.contractPath, {
|
|
240
243
|
sourceCodeHash: c.sourceCodeHash,
|
|
244
|
+
bytecodeDebugPatch: '',
|
|
245
|
+
codeHashDebug: '',
|
|
241
246
|
warnings: []
|
|
242
247
|
})
|
|
243
248
|
})
|
|
@@ -327,7 +332,9 @@ export class Project {
|
|
|
327
332
|
}
|
|
328
333
|
|
|
329
334
|
contractByCodeHash(codeHash: string): Contract {
|
|
330
|
-
const contract = this.contracts.find(
|
|
335
|
+
const contract = this.contracts.find(
|
|
336
|
+
(c) => c.artifact.codeHash === codeHash || c.artifact.codeHashDebug == codeHash
|
|
337
|
+
)
|
|
331
338
|
if (typeof contract === 'undefined') {
|
|
332
339
|
throw new Error(`Unknown code with code hash: ${codeHash}`)
|
|
333
340
|
}
|
|
@@ -394,10 +401,10 @@ export class Project {
|
|
|
394
401
|
const warnings = info.warnings
|
|
395
402
|
const artifactDir = file.getArtifactPath(artifactsRootDir)
|
|
396
403
|
if (file.type === SourceType.Contract) {
|
|
397
|
-
const artifact = await Contract.fromArtifactFile(artifactDir)
|
|
404
|
+
const artifact = await Contract.fromArtifactFile(artifactDir, info.bytecodeDebugPatch, info.codeHashDebug)
|
|
398
405
|
contracts.push(new Compiled(file, artifact, warnings))
|
|
399
406
|
} else if (file.type === SourceType.Script) {
|
|
400
|
-
const artifact = await Script.fromArtifactFile(artifactDir)
|
|
407
|
+
const artifact = await Script.fromArtifactFile(artifactDir, info.bytecodeDebugPatch)
|
|
401
408
|
scripts.push(new Compiled(file, artifact, warnings))
|
|
402
409
|
}
|
|
403
410
|
}
|
|
@@ -526,27 +533,37 @@ export abstract class Artifact {
|
|
|
526
533
|
|
|
527
534
|
export class Contract extends Artifact {
|
|
528
535
|
readonly bytecode: string
|
|
536
|
+
readonly bytecodeDebugPatch: string
|
|
529
537
|
readonly codeHash: string
|
|
530
538
|
readonly fieldsSig: FieldsSig
|
|
531
539
|
readonly eventsSig: EventSig[]
|
|
532
540
|
|
|
541
|
+
readonly bytecodeDebug: string
|
|
542
|
+
readonly codeHashDebug: string
|
|
543
|
+
|
|
533
544
|
constructor(
|
|
534
545
|
name: string,
|
|
535
546
|
bytecode: string,
|
|
547
|
+
bytecodeDebugPatch: string,
|
|
536
548
|
codeHash: string,
|
|
549
|
+
codeHashDebug: string,
|
|
537
550
|
fieldsSig: FieldsSig,
|
|
538
551
|
eventsSig: EventSig[],
|
|
539
552
|
functions: FunctionSig[]
|
|
540
553
|
) {
|
|
541
554
|
super(name, functions)
|
|
542
555
|
this.bytecode = bytecode
|
|
556
|
+
this.bytecodeDebugPatch = bytecodeDebugPatch
|
|
543
557
|
this.codeHash = codeHash
|
|
544
558
|
this.fieldsSig = fieldsSig
|
|
545
559
|
this.eventsSig = eventsSig
|
|
560
|
+
|
|
561
|
+
this.bytecodeDebug = ralph.buildDebugBytecode(this.bytecode, this.bytecodeDebugPatch)
|
|
562
|
+
this.codeHashDebug = codeHashDebug
|
|
546
563
|
}
|
|
547
564
|
|
|
548
565
|
// TODO: safely parse json
|
|
549
|
-
static fromJson(artifact: any): Contract {
|
|
566
|
+
static fromJson(artifact: any, bytecodeDebugPatch = '', codeHashDebug = ''): Contract {
|
|
550
567
|
if (
|
|
551
568
|
artifact.name == null ||
|
|
552
569
|
artifact.bytecode == null ||
|
|
@@ -560,7 +577,9 @@ export class Contract extends Artifact {
|
|
|
560
577
|
const contract = new Contract(
|
|
561
578
|
artifact.name,
|
|
562
579
|
artifact.bytecode,
|
|
580
|
+
bytecodeDebugPatch,
|
|
563
581
|
artifact.codeHash,
|
|
582
|
+
codeHashDebug ? codeHashDebug : artifact.codeHash,
|
|
564
583
|
artifact.fieldsSig,
|
|
565
584
|
artifact.eventsSig,
|
|
566
585
|
artifact.functions
|
|
@@ -569,14 +588,23 @@ export class Contract extends Artifact {
|
|
|
569
588
|
}
|
|
570
589
|
|
|
571
590
|
static fromCompileResult(result: node.CompileContractResult): Contract {
|
|
572
|
-
return new Contract(
|
|
591
|
+
return new Contract(
|
|
592
|
+
result.name,
|
|
593
|
+
result.bytecode,
|
|
594
|
+
result.bytecodeDebugPatch,
|
|
595
|
+
result.codeHash,
|
|
596
|
+
result.codeHashDebug,
|
|
597
|
+
result.fields,
|
|
598
|
+
result.events,
|
|
599
|
+
result.functions
|
|
600
|
+
)
|
|
573
601
|
}
|
|
574
602
|
|
|
575
603
|
// support both 'code.ral' and 'code.ral.json'
|
|
576
|
-
static async fromArtifactFile(path: string): Promise<Contract> {
|
|
604
|
+
static async fromArtifactFile(path: string, bytecodeDebugPatch: string, codeHashDebug: string): Promise<Contract> {
|
|
577
605
|
const content = await fsPromises.readFile(path)
|
|
578
606
|
const artifact = JSON.parse(content.toString())
|
|
579
|
-
return Contract.fromJson(artifact)
|
|
607
|
+
return Contract.fromJson(artifact, bytecodeDebugPatch, codeHashDebug)
|
|
580
608
|
}
|
|
581
609
|
|
|
582
610
|
async fetchState(address: string, group: number): Promise<ContractState> {
|
|
@@ -619,11 +647,19 @@ export class Contract extends Artifact {
|
|
|
619
647
|
return bs58.encode(bytes)
|
|
620
648
|
}
|
|
621
649
|
|
|
650
|
+
private _printDebugMessages(funcName: string, messages: DebugMessage[]) {
|
|
651
|
+
if (messages.length != 0) {
|
|
652
|
+
console.log(`Testing ${this.name}.${funcName}:`)
|
|
653
|
+
messages.forEach((m) => console.log(`Debug - ${m.contractAddress} - ${m.message}`))
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
622
657
|
private async _test(
|
|
623
658
|
funcName: string,
|
|
624
659
|
params: TestContractParams,
|
|
625
660
|
expectPublic: boolean,
|
|
626
|
-
accessType: string
|
|
661
|
+
accessType: string,
|
|
662
|
+
printDebugMessages: boolean
|
|
627
663
|
): Promise<TestContractResult> {
|
|
628
664
|
const apiParams: node.TestContract = this.toTestContract(funcName, params)
|
|
629
665
|
const apiResult = await Project.currentProject.nodeProvider.contracts.postContractsTestContract(apiParams)
|
|
@@ -631,6 +667,9 @@ export class Contract extends Artifact {
|
|
|
631
667
|
const methodIndex =
|
|
632
668
|
typeof params.testMethodIndex !== 'undefined' ? params.testMethodIndex : this.getMethodIndex(funcName)
|
|
633
669
|
const isPublic = this.functions[`${methodIndex}`].isPublic
|
|
670
|
+
if (printDebugMessages) {
|
|
671
|
+
this._printDebugMessages(funcName, apiResult.debugMessages)
|
|
672
|
+
}
|
|
634
673
|
if (isPublic === expectPublic) {
|
|
635
674
|
const result = await this.fromTestContractResult(methodIndex, apiResult)
|
|
636
675
|
return result
|
|
@@ -639,12 +678,20 @@ export class Contract extends Artifact {
|
|
|
639
678
|
}
|
|
640
679
|
}
|
|
641
680
|
|
|
642
|
-
async testPublicMethod(
|
|
643
|
-
|
|
681
|
+
async testPublicMethod(
|
|
682
|
+
funcName: string,
|
|
683
|
+
params: TestContractParams,
|
|
684
|
+
printDebugMessages = true
|
|
685
|
+
): Promise<TestContractResult> {
|
|
686
|
+
return this._test(funcName, params, true, 'public', printDebugMessages)
|
|
644
687
|
}
|
|
645
688
|
|
|
646
|
-
async testPrivateMethod(
|
|
647
|
-
|
|
689
|
+
async testPrivateMethod(
|
|
690
|
+
funcName: string,
|
|
691
|
+
params: TestContractParams,
|
|
692
|
+
printDebugMessages = true
|
|
693
|
+
): Promise<TestContractResult> {
|
|
694
|
+
return this._test(funcName, params, false, 'private', printDebugMessages)
|
|
648
695
|
}
|
|
649
696
|
|
|
650
697
|
toApiFields(fields?: Fields): node.Val[] {
|
|
@@ -680,7 +727,7 @@ export class Contract extends Artifact {
|
|
|
680
727
|
return {
|
|
681
728
|
group: params.group,
|
|
682
729
|
address: params.address,
|
|
683
|
-
bytecode: this.
|
|
730
|
+
bytecode: this.bytecodeDebug,
|
|
684
731
|
initialFields: this.toApiFields(params.initialFields),
|
|
685
732
|
initialAsset: typeof params.initialAsset !== 'undefined' ? toApiAsset(params.initialAsset) : undefined,
|
|
686
733
|
methodIndex: this.getMethodIndex(funcName),
|
|
@@ -746,6 +793,7 @@ export class Contract extends Artifact {
|
|
|
746
793
|
return {
|
|
747
794
|
address: result.address,
|
|
748
795
|
contractId: binToHex(contractIdFromAddress(result.address)),
|
|
796
|
+
contractAddress: result.address,
|
|
749
797
|
returns: fromApiArray(result.returns, this.functions[`${methodIndex}`].returnTypes),
|
|
750
798
|
gasUsed: result.gasUsed,
|
|
751
799
|
contracts: await Promise.all(result.contracts.map((contract) => this.fromApiContractState(contract))),
|
|
@@ -760,7 +808,8 @@ export class Contract extends Artifact {
|
|
|
760
808
|
throw Error(`Cannot find codeHash for the contract address: ${contractAddress}`)
|
|
761
809
|
}
|
|
762
810
|
})
|
|
763
|
-
)
|
|
811
|
+
),
|
|
812
|
+
debugMessages: result.debugMessages
|
|
764
813
|
}
|
|
765
814
|
}
|
|
766
815
|
|
|
@@ -797,20 +846,28 @@ export class Contract extends Artifact {
|
|
|
797
846
|
|
|
798
847
|
export class Script extends Artifact {
|
|
799
848
|
readonly bytecodeTemplate: string
|
|
849
|
+
readonly bytecodeDebugPatch: string
|
|
800
850
|
readonly fieldsSig: FieldsSig
|
|
801
851
|
|
|
802
|
-
constructor(
|
|
852
|
+
constructor(
|
|
853
|
+
name: string,
|
|
854
|
+
bytecodeTemplate: string,
|
|
855
|
+
bytecodeDebugPatch: string,
|
|
856
|
+
fieldsSig: FieldsSig,
|
|
857
|
+
functions: FunctionSig[]
|
|
858
|
+
) {
|
|
803
859
|
super(name, functions)
|
|
804
860
|
this.bytecodeTemplate = bytecodeTemplate
|
|
861
|
+
this.bytecodeDebugPatch = bytecodeDebugPatch
|
|
805
862
|
this.fieldsSig = fieldsSig
|
|
806
863
|
}
|
|
807
864
|
|
|
808
865
|
static fromCompileResult(result: node.CompileScriptResult): Script {
|
|
809
|
-
return new Script(result.name, result.bytecodeTemplate, result.fields, result.functions)
|
|
866
|
+
return new Script(result.name, result.bytecodeTemplate, result.bytecodeDebugPatch, result.fields, result.functions)
|
|
810
867
|
}
|
|
811
868
|
|
|
812
869
|
// TODO: safely parse json
|
|
813
|
-
static fromJson(artifact: any): Script {
|
|
870
|
+
static fromJson(artifact: any, bytecodeDebugPatch = ''): Script {
|
|
814
871
|
if (
|
|
815
872
|
artifact.name == null ||
|
|
816
873
|
artifact.bytecodeTemplate == null ||
|
|
@@ -819,13 +876,19 @@ export class Script extends Artifact {
|
|
|
819
876
|
) {
|
|
820
877
|
throw Error('The artifact JSON for script is incomplete')
|
|
821
878
|
}
|
|
822
|
-
return new Script(
|
|
879
|
+
return new Script(
|
|
880
|
+
artifact.name,
|
|
881
|
+
artifact.bytecodeTemplate,
|
|
882
|
+
bytecodeDebugPatch,
|
|
883
|
+
artifact.fieldsSig,
|
|
884
|
+
artifact.functions
|
|
885
|
+
)
|
|
823
886
|
}
|
|
824
887
|
|
|
825
|
-
static async fromArtifactFile(path: string): Promise<Script> {
|
|
888
|
+
static async fromArtifactFile(path: string, bytecodeDebugPatch: string): Promise<Script> {
|
|
826
889
|
const content = await fsPromises.readFile(path)
|
|
827
890
|
const artifact = JSON.parse(content.toString())
|
|
828
|
-
return this.fromJson(artifact)
|
|
891
|
+
return this.fromJson(artifact, bytecodeDebugPatch)
|
|
829
892
|
}
|
|
830
893
|
|
|
831
894
|
override toString(): string {
|
|
@@ -981,14 +1044,18 @@ export interface ContractEventByTxId {
|
|
|
981
1044
|
fields: Fields
|
|
982
1045
|
}
|
|
983
1046
|
|
|
1047
|
+
export type DebugMessage = node.DebugMessage
|
|
1048
|
+
|
|
984
1049
|
export interface TestContractResult {
|
|
985
1050
|
address: string
|
|
986
1051
|
contractId: string
|
|
1052
|
+
contractAddress: string
|
|
987
1053
|
returns: Val[]
|
|
988
1054
|
gasUsed: number
|
|
989
1055
|
contracts: ContractState[]
|
|
990
1056
|
txOutputs: Output[]
|
|
991
1057
|
events: ContractEventByTxId[]
|
|
1058
|
+
debugMessages: DebugMessage[]
|
|
992
1059
|
}
|
|
993
1060
|
export declare type Output = AssetOutput | ContractOutput
|
|
994
1061
|
export interface AssetOutput extends Asset {
|
package/src/contract/ralph.ts
CHANGED
|
@@ -343,6 +343,31 @@ function invalidVal(tpe: string, value: Val): Error {
|
|
|
343
343
|
return Error(`Invalid API value ${value} for type ${tpe}`)
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
+
export function buildDebugBytecode(bytecode: string, bytecodePatch: string): string {
|
|
347
|
+
if (bytecodePatch === '') {
|
|
348
|
+
return bytecode
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const pattern = /[=+-][0-9a-f]*/g
|
|
352
|
+
let result = ''
|
|
353
|
+
let index = 0
|
|
354
|
+
for (const parts of bytecodePatch.matchAll(pattern)) {
|
|
355
|
+
const part = parts[0]
|
|
356
|
+
const diffType = part[0]
|
|
357
|
+
if (diffType === '=') {
|
|
358
|
+
const length = parseInt(part.substring(1))
|
|
359
|
+
result = result + bytecode.slice(index, index + length)
|
|
360
|
+
index = index + length
|
|
361
|
+
} else if (diffType === '+') {
|
|
362
|
+
result = result + part.substring(1)
|
|
363
|
+
} else {
|
|
364
|
+
const length = parseInt(part.substring(1))
|
|
365
|
+
index = index + length
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return result
|
|
369
|
+
}
|
|
370
|
+
|
|
346
371
|
// export function buildContractByteCode(
|
|
347
372
|
// compiled: node.TemplateContractByteCode,
|
|
348
373
|
// templateVariables: TemplateVariables
|