@alephium/web3 2.0.2 → 2.0.3
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/contract/contract.d.ts +1 -2
- package/dist/src/contract/contract.js +1 -43
- package/dist/src/contract/ralph.d.ts +0 -1
- package/dist/src/contract/ralph.js +1 -26
- package/dist/src/signer/tx-builder.d.ts +3 -0
- package/dist/src/signer/tx-builder.js +65 -3
- package/package.json +1 -1
- package/src/contract/contract.ts +3 -58
- package/src/contract/ralph.ts +0 -26
- package/src/signer/tx-builder.ts +72 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NamedVals, node, NodeProvider, Number256, Token, Val } from '../api';
|
|
2
|
-
import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScriptTxParams, SignerProvider, Address, SignExecuteScriptTxResult
|
|
2
|
+
import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScriptTxParams, SignerProvider, Address, SignExecuteScriptTxResult } from '../signer';
|
|
3
3
|
import { Optional, HexString } from '../utils';
|
|
4
4
|
import { EventSubscribeOptions, EventSubscription } from './events';
|
|
5
5
|
import { contract, Method } from '../codec';
|
|
@@ -101,7 +101,6 @@ export declare class Script extends Artifact {
|
|
|
101
101
|
static fromJson(artifact: any, bytecodeDebugPatch?: string, structs?: Struct[]): Script;
|
|
102
102
|
static fromArtifactFile(path: string, bytecodeDebugPatch: string, structs?: Struct[]): Promise<Script>;
|
|
103
103
|
toString(): string;
|
|
104
|
-
getBytecodeAndGroup<P extends Fields>(account: Account, fields: P): [string, number];
|
|
105
104
|
txParamsForExecution<P extends Fields>(params: ExecuteScriptParams<P>): Promise<SignExecuteScriptTxParams>;
|
|
106
105
|
buildByteCodeToDeploy(initialFields: Fields): string;
|
|
107
106
|
}
|
|
@@ -43,7 +43,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
43
43
|
exports.getContractCodeByCodeHash = exports.getTokenIdFromUnsignedTx = exports.getContractIdFromUnsignedTx = exports.getContractEventsCurrentCount = exports.multicallMethods = exports.signExecuteMethod = exports.callMethod = exports.subscribeContractEvents = exports.subscribeContractEvent = exports.decodeEvent = exports.subscribeContractDestroyedEvent = exports.subscribeContractCreatedEvent = exports.fetchContractState = exports.ContractInstance = exports.getMapItem = exports.RalphMap = exports.printDebugMessagesFromTx = exports.getDebugMessagesFromTx = exports.testMethod = exports.extractMapsFromApiResult = exports.addStdIdToFields = exports.subscribeEventsFromContract = exports.decodeContractDestroyedEvent = exports.decodeContractCreatedEvent = exports.DestroyContractEventAddresses = exports.CreateContractEventAddresses = exports.ExecutableScript = exports.ContractFactory = exports.randomTxId = exports.fromApiEventFields = exports.fromApiArray = exports.getDefaultValue = exports.fromApiFields = exports.Script = exports.Contract = exports.Artifact = exports.Struct = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = exports.StdIdFieldName = void 0;
|
|
44
44
|
const fs_1 = require("fs");
|
|
45
45
|
const api_1 = require("../api");
|
|
46
|
-
const signer_1 = require("../signer");
|
|
47
46
|
const ralph = __importStar(require("./ralph"));
|
|
48
47
|
const utils_1 = require("../utils");
|
|
49
48
|
const address_1 = require("../address");
|
|
@@ -54,7 +53,6 @@ const blake = __importStar(require("blakejs"));
|
|
|
54
53
|
const debug_1 = require("../debug");
|
|
55
54
|
const codec_1 = require("../codec");
|
|
56
55
|
const error_1 = require("../error");
|
|
57
|
-
const script_codec_1 = require("../codec/script-codec");
|
|
58
56
|
const crypto = new utils_1.WebCrypto();
|
|
59
57
|
exports.StdIdFieldName = '__stdInterfaceId';
|
|
60
58
|
exports.DEFAULT_NODE_COMPILER_OPTIONS = {
|
|
@@ -522,23 +520,9 @@ class Script extends Artifact {
|
|
|
522
520
|
};
|
|
523
521
|
return JSON.stringify(object, null, 2);
|
|
524
522
|
}
|
|
525
|
-
getBytecodeAndGroup(account, fields) {
|
|
526
|
-
const bytecode = this.buildByteCodeToDeploy(fields);
|
|
527
|
-
if ((0, signer_1.isGroupedAccount)(account)) {
|
|
528
|
-
return [bytecode, account.group];
|
|
529
|
-
}
|
|
530
|
-
const group = getGroupFromTxScript(bytecode);
|
|
531
|
-
const defaultGroup = (0, address_1.groupOfAddress)(account.address);
|
|
532
|
-
if (group === undefined || group === defaultGroup) {
|
|
533
|
-
return [bytecode, defaultGroup];
|
|
534
|
-
}
|
|
535
|
-
const newFields = ralph.updateFieldsWithGroup(fields, group);
|
|
536
|
-
const newBytecode = this.buildByteCodeToDeploy(newFields);
|
|
537
|
-
return [newBytecode, group];
|
|
538
|
-
}
|
|
539
523
|
async txParamsForExecution(params) {
|
|
540
524
|
const selectedAccount = await params.signer.getSelectedAccount();
|
|
541
|
-
const
|
|
525
|
+
const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {});
|
|
542
526
|
const signerParams = {
|
|
543
527
|
signerAddress: selectedAccount.address,
|
|
544
528
|
signerKeyType: selectedAccount.keyType,
|
|
@@ -547,7 +531,6 @@ class Script extends Artifact {
|
|
|
547
531
|
tokens: params.tokens,
|
|
548
532
|
gasAmount: params.gasAmount,
|
|
549
533
|
gasPrice: params.gasPrice,
|
|
550
|
-
group,
|
|
551
534
|
dustAmount: params.dustAmount
|
|
552
535
|
};
|
|
553
536
|
return signerParams;
|
|
@@ -562,31 +545,6 @@ class Script extends Artifact {
|
|
|
562
545
|
}
|
|
563
546
|
}
|
|
564
547
|
exports.Script = Script;
|
|
565
|
-
function getGroupFromTxScript(bytecode) {
|
|
566
|
-
const script = script_codec_1.scriptCodec.decode((0, utils_1.hexToBinUnsafe)(bytecode));
|
|
567
|
-
const instrs = script.methods.flatMap((method) => method.instrs);
|
|
568
|
-
for (let index = 0; index < instrs.length - 1; index += 1) {
|
|
569
|
-
const instr = instrs[`${index}`];
|
|
570
|
-
const nextInstr = instrs[index + 1];
|
|
571
|
-
if (instr.name === 'BytesConst' &&
|
|
572
|
-
instr.value.length === 32 &&
|
|
573
|
-
(nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')) {
|
|
574
|
-
const groupIndex = instr.value[instr.value.length - 1];
|
|
575
|
-
if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
|
|
576
|
-
return groupIndex;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
for (const instr of instrs) {
|
|
581
|
-
if (instr.name === 'BytesConst' && instr.value.length === 32) {
|
|
582
|
-
const groupIndex = instr.value[instr.value.length - 1];
|
|
583
|
-
if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
|
|
584
|
-
return groupIndex;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return undefined;
|
|
589
|
-
}
|
|
590
548
|
function fromApiFields(immFields, mutFields, fieldsSig, structs) {
|
|
591
549
|
let [immIndex, mutIndex] = [0, 0];
|
|
592
550
|
const func = (type, isMutable) => {
|
|
@@ -63,7 +63,6 @@ export declare function flattenFields(fields: Fields, names: string[], types: st
|
|
|
63
63
|
value: Val;
|
|
64
64
|
isMutable: boolean;
|
|
65
65
|
}[];
|
|
66
|
-
export declare function updateFieldsWithGroup(fields: Fields, group: number): Fields;
|
|
67
66
|
export declare function buildScriptByteCode(bytecodeTemplate: string, fields: Fields, fieldsSig: FieldsSig, structs: Struct[]): string;
|
|
68
67
|
export declare function encodeContractFields(fields: Fields, fieldsSig: FieldsSig, structs: Struct[]): {
|
|
69
68
|
encodedImmFields: Uint8Array;
|
|
@@ -17,7 +17,7 @@ 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.buildDebugBytecode = exports.encodeContractField = exports.buildContractByteCode = exports.encodeContractFields = exports.buildScriptByteCode = exports.
|
|
20
|
+
exports.buildDebugBytecode = exports.encodeContractField = exports.buildContractByteCode = exports.encodeContractFields = exports.buildScriptByteCode = exports.flattenFields = exports.typeLength = exports.encodeMapKey = exports.decodePrimitive = exports.tryDecodeMapDebugLog = exports.calcFieldSize = exports.encodeMapPrefix = exports.parseMapType = exports.splitFields = exports.encodeScriptField = exports.encodeScriptFieldAsString = exports.encodePrimitiveValues = exports.addressVal = exports.byteVecVal = exports.u256Val = exports.i256Val = exports.boolVal = exports.encodeVmAddress = exports.encodeVmByteVec = exports.encodeVmU256 = exports.encodeVmI256 = exports.encodeVmBool = exports.VmValType = exports.encodeAddress = exports.encodeByteVec = void 0;
|
|
21
21
|
const api_1 = require("../api");
|
|
22
22
|
const utils_1 = require("../utils");
|
|
23
23
|
const codec_1 = require("../codec");
|
|
@@ -336,31 +336,6 @@ function checkPrimitiveValue(name, ralphType, value) {
|
|
|
336
336
|
}
|
|
337
337
|
throw Error(`Invalid value ${value} for ${name}, expected a value of type ${ralphType}`);
|
|
338
338
|
}
|
|
339
|
-
function updateFieldsWithGroup(fields, group) {
|
|
340
|
-
const newFields = {};
|
|
341
|
-
for (const key in fields) {
|
|
342
|
-
const value = fields[`${key}`];
|
|
343
|
-
newFields[`${key}`] = updateValWithGroup(value, group);
|
|
344
|
-
}
|
|
345
|
-
return newFields;
|
|
346
|
-
}
|
|
347
|
-
exports.updateFieldsWithGroup = updateFieldsWithGroup;
|
|
348
|
-
function updateValWithGroup(value, group) {
|
|
349
|
-
if (typeof value === 'string') {
|
|
350
|
-
if (!(0, address_1.isValidAddress)(value))
|
|
351
|
-
return value;
|
|
352
|
-
if ((0, address_1.isGrouplessAddressWithoutGroupIndex)(value))
|
|
353
|
-
return `${value}:${group}`;
|
|
354
|
-
return value;
|
|
355
|
-
}
|
|
356
|
-
if (Array.isArray(value)) {
|
|
357
|
-
return value.map((v) => updateValWithGroup(v, group));
|
|
358
|
-
}
|
|
359
|
-
if (typeof value === 'object') {
|
|
360
|
-
return updateFieldsWithGroup(value, group);
|
|
361
|
-
}
|
|
362
|
-
return value;
|
|
363
|
-
}
|
|
364
339
|
const scriptFieldRegex = /\{([0-9]*)\}/g;
|
|
365
340
|
function buildScriptByteCode(bytecodeTemplate, fields, fieldsSig, structs) {
|
|
366
341
|
const allFields = flattenFields(fields, fieldsSig.names, fieldsSig.types, fieldsSig.isMutable, structs);
|
|
@@ -12,8 +12,11 @@ export declare abstract class TransactionBuilder {
|
|
|
12
12
|
static buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'>;
|
|
13
13
|
private buildTransferTxParams;
|
|
14
14
|
private buildDeployContractTxParams;
|
|
15
|
+
private static checkAndGetParams;
|
|
15
16
|
private buildExecuteScriptTxParams;
|
|
16
17
|
private convertTransferTxResult;
|
|
17
18
|
private convertDeployContractTxResult;
|
|
18
19
|
private convertExecuteScriptTxResult;
|
|
19
20
|
}
|
|
21
|
+
export declare function getGroupFromTxScript(bytecode: string): number | undefined;
|
|
22
|
+
export declare function updateBytecodeWithGroup(bytecode: string, group: number): string;
|
|
@@ -17,14 +17,17 @@ 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.TransactionBuilder = void 0;
|
|
20
|
+
exports.updateBytecodeWithGroup = exports.getGroupFromTxScript = exports.TransactionBuilder = void 0;
|
|
21
21
|
const utils_1 = require("../utils");
|
|
22
22
|
const api_1 = require("../api");
|
|
23
23
|
const address_1 = require("../address");
|
|
24
24
|
const signer_1 = require("./signer");
|
|
25
|
+
const types_1 = require("./types");
|
|
25
26
|
const codec_1 = require("../codec");
|
|
26
27
|
const transaction_1 = require("../transaction");
|
|
27
28
|
const hash_1 = require("../codec/hash");
|
|
29
|
+
const constants_1 = require("../constants");
|
|
30
|
+
const script_codec_1 = require("../codec/script-codec");
|
|
28
31
|
class TransactionBuilder {
|
|
29
32
|
static from(param0, param1, customFetch) {
|
|
30
33
|
const nodeProvider = typeof param0 === 'string' ? new api_1.NodeProvider(param0, param1, customFetch) : param0;
|
|
@@ -147,12 +150,29 @@ class TransactionBuilder {
|
|
|
147
150
|
...rest
|
|
148
151
|
};
|
|
149
152
|
}
|
|
153
|
+
static checkAndGetParams(params) {
|
|
154
|
+
if ((0, types_1.isGroupedKeyType)(params.signerKeyType ?? 'default')) {
|
|
155
|
+
return params;
|
|
156
|
+
}
|
|
157
|
+
if (!(0, address_1.isGrouplessAddress)(params.signerAddress)) {
|
|
158
|
+
throw new Error('Invalid signer key type for groupless address');
|
|
159
|
+
}
|
|
160
|
+
const group = params.group ?? getGroupFromTxScript(params.bytecode);
|
|
161
|
+
const defaultGroup = (0, address_1.groupOfAddress)(params.signerAddress);
|
|
162
|
+
if (group === undefined || group === defaultGroup) {
|
|
163
|
+
return { ...params, group: defaultGroup };
|
|
164
|
+
}
|
|
165
|
+
const newBytecode = updateBytecodeWithGroup(params.bytecode, group);
|
|
166
|
+
const newParams = { ...params, bytecode: newBytecode };
|
|
167
|
+
return { ...newParams, group };
|
|
168
|
+
}
|
|
150
169
|
buildExecuteScriptTxParams(params, publicKey) {
|
|
151
170
|
TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType);
|
|
152
|
-
const
|
|
171
|
+
const newParams = TransactionBuilder.checkAndGetParams(params);
|
|
172
|
+
const { signerKeyType, attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = newParams;
|
|
153
173
|
return {
|
|
154
174
|
fromPublicKey: publicKey,
|
|
155
|
-
fromPublicKeyType:
|
|
175
|
+
fromPublicKeyType: signerKeyType,
|
|
156
176
|
attoAlphAmount: (0, api_1.toApiNumber256Optional)(attoAlphAmount),
|
|
157
177
|
tokens: (0, api_1.toApiTokens)(tokens),
|
|
158
178
|
gasPrice: (0, api_1.toApiNumber256Optional)(gasPrice),
|
|
@@ -229,3 +249,45 @@ class TransactionBuilder {
|
|
|
229
249
|
}
|
|
230
250
|
}
|
|
231
251
|
exports.TransactionBuilder = TransactionBuilder;
|
|
252
|
+
function getGroupFromTxScript(bytecode) {
|
|
253
|
+
const script = script_codec_1.scriptCodec.decode((0, utils_1.hexToBinUnsafe)(bytecode));
|
|
254
|
+
const instrs = script.methods.flatMap((method) => method.instrs);
|
|
255
|
+
for (let index = 0; index < instrs.length - 1; index += 1) {
|
|
256
|
+
const instr = instrs[`${index}`];
|
|
257
|
+
const nextInstr = instrs[index + 1];
|
|
258
|
+
if (instr.name === 'BytesConst' &&
|
|
259
|
+
instr.value.length === 32 &&
|
|
260
|
+
(nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')) {
|
|
261
|
+
const groupIndex = instr.value[instr.value.length - 1];
|
|
262
|
+
if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
|
|
263
|
+
return groupIndex;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
for (const instr of instrs) {
|
|
268
|
+
if (instr.name === 'BytesConst' && instr.value.length === 32) {
|
|
269
|
+
const groupIndex = instr.value[instr.value.length - 1];
|
|
270
|
+
if (groupIndex >= 0 && groupIndex < constants_1.TOTAL_NUMBER_OF_GROUPS) {
|
|
271
|
+
return groupIndex;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
exports.getGroupFromTxScript = getGroupFromTxScript;
|
|
278
|
+
function updateBytecodeWithGroup(bytecode, group) {
|
|
279
|
+
const script = script_codec_1.scriptCodec.decode((0, utils_1.hexToBinUnsafe)(bytecode));
|
|
280
|
+
const newMethods = script.methods.map((method) => {
|
|
281
|
+
const newInstrs = method.instrs.map((instr) => {
|
|
282
|
+
if (instr.name === 'AddressConst' && instr.value.kind === 'P2PK') {
|
|
283
|
+
const newLockupScript = { ...instr.value, value: { ...instr.value.value, group } };
|
|
284
|
+
return { ...instr, value: newLockupScript };
|
|
285
|
+
}
|
|
286
|
+
return instr;
|
|
287
|
+
});
|
|
288
|
+
return { ...method, instrs: newInstrs };
|
|
289
|
+
});
|
|
290
|
+
const bytes = script_codec_1.scriptCodec.encode({ methods: newMethods });
|
|
291
|
+
return (0, utils_1.binToHex)(bytes);
|
|
292
|
+
}
|
|
293
|
+
exports.updateBytecodeWithGroup = updateBytecodeWithGroup;
|
package/package.json
CHANGED
package/src/contract/contract.ts
CHANGED
|
@@ -42,9 +42,7 @@ import {
|
|
|
42
42
|
SignExecuteScriptTxParams,
|
|
43
43
|
SignerProvider,
|
|
44
44
|
Address,
|
|
45
|
-
SignExecuteScriptTxResult
|
|
46
|
-
Account,
|
|
47
|
-
isGroupedAccount
|
|
45
|
+
SignExecuteScriptTxResult
|
|
48
46
|
} from '../signer'
|
|
49
47
|
import * as ralph from './ralph'
|
|
50
48
|
import {
|
|
@@ -61,13 +59,7 @@ import {
|
|
|
61
59
|
isHexString,
|
|
62
60
|
hexToString
|
|
63
61
|
} from '../utils'
|
|
64
|
-
import {
|
|
65
|
-
contractIdFromAddress,
|
|
66
|
-
groupOfAddress,
|
|
67
|
-
addressFromContractId,
|
|
68
|
-
subContractId,
|
|
69
|
-
isGrouplessAddressWithoutGroupIndex
|
|
70
|
-
} from '../address'
|
|
62
|
+
import { contractIdFromAddress, groupOfAddress, addressFromContractId, subContractId } from '../address'
|
|
71
63
|
import { getCurrentNodeProvider } from '../global'
|
|
72
64
|
import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
|
|
73
65
|
import { MINIMAL_CONTRACT_DEPOSIT, ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
@@ -100,7 +92,6 @@ import {
|
|
|
100
92
|
} from '../codec'
|
|
101
93
|
import { TraceableError } from '../error'
|
|
102
94
|
import { SimulationResult } from '../api/api-alephium'
|
|
103
|
-
import { scriptCodec } from '../codec/script-codec'
|
|
104
95
|
|
|
105
96
|
const crypto = new WebCrypto()
|
|
106
97
|
|
|
@@ -796,26 +787,9 @@ export class Script extends Artifact {
|
|
|
796
787
|
return JSON.stringify(object, null, 2)
|
|
797
788
|
}
|
|
798
789
|
|
|
799
|
-
getBytecodeAndGroup<P extends Fields>(account: Account, fields: P): [string, number] {
|
|
800
|
-
const bytecode = this.buildByteCodeToDeploy(fields)
|
|
801
|
-
if (isGroupedAccount(account)) {
|
|
802
|
-
return [bytecode, account.group]
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
const group = getGroupFromTxScript(bytecode)
|
|
806
|
-
const defaultGroup = groupOfAddress(account.address)
|
|
807
|
-
if (group === undefined || group === defaultGroup) {
|
|
808
|
-
return [bytecode, defaultGroup]
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
const newFields = ralph.updateFieldsWithGroup(fields, group) as P
|
|
812
|
-
const newBytecode = this.buildByteCodeToDeploy(newFields)
|
|
813
|
-
return [newBytecode, group]
|
|
814
|
-
}
|
|
815
|
-
|
|
816
790
|
async txParamsForExecution<P extends Fields>(params: ExecuteScriptParams<P>): Promise<SignExecuteScriptTxParams> {
|
|
817
791
|
const selectedAccount = await params.signer.getSelectedAccount()
|
|
818
|
-
const
|
|
792
|
+
const bytecode = this.buildByteCodeToDeploy(params.initialFields ?? {})
|
|
819
793
|
const signerParams: SignExecuteScriptTxParams = {
|
|
820
794
|
signerAddress: selectedAccount.address,
|
|
821
795
|
signerKeyType: selectedAccount.keyType,
|
|
@@ -824,7 +798,6 @@ export class Script extends Artifact {
|
|
|
824
798
|
tokens: params.tokens,
|
|
825
799
|
gasAmount: params.gasAmount,
|
|
826
800
|
gasPrice: params.gasPrice,
|
|
827
|
-
group,
|
|
828
801
|
dustAmount: params.dustAmount
|
|
829
802
|
}
|
|
830
803
|
return signerParams
|
|
@@ -839,34 +812,6 @@ export class Script extends Artifact {
|
|
|
839
812
|
}
|
|
840
813
|
}
|
|
841
814
|
|
|
842
|
-
function getGroupFromTxScript(bytecode: string): number | undefined {
|
|
843
|
-
const script = scriptCodec.decode(hexToBinUnsafe(bytecode))
|
|
844
|
-
const instrs = script.methods.flatMap((method) => method.instrs)
|
|
845
|
-
for (let index = 0; index < instrs.length - 1; index += 1) {
|
|
846
|
-
const instr = instrs[`${index}`]
|
|
847
|
-
const nextInstr = instrs[index + 1]
|
|
848
|
-
if (
|
|
849
|
-
instr.name === 'BytesConst' &&
|
|
850
|
-
instr.value.length === 32 &&
|
|
851
|
-
(nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')
|
|
852
|
-
) {
|
|
853
|
-
const groupIndex = instr.value[instr.value.length - 1]
|
|
854
|
-
if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
|
|
855
|
-
return groupIndex
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
for (const instr of instrs) {
|
|
860
|
-
if (instr.name === 'BytesConst' && instr.value.length === 32) {
|
|
861
|
-
const groupIndex = instr.value[instr.value.length - 1]
|
|
862
|
-
if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
|
|
863
|
-
return groupIndex
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
return undefined
|
|
868
|
-
}
|
|
869
|
-
|
|
870
815
|
export function fromApiFields(
|
|
871
816
|
immFields: node.Val[],
|
|
872
817
|
mutFields: node.Val[],
|
package/src/contract/ralph.ts
CHANGED
|
@@ -399,32 +399,6 @@ function checkPrimitiveValue(name: string, ralphType: string, value: Val): strin
|
|
|
399
399
|
throw Error(`Invalid value ${value} for ${name}, expected a value of type ${ralphType}`)
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
export function updateFieldsWithGroup(fields: Fields, group: number): Fields {
|
|
403
|
-
const newFields: Fields = {}
|
|
404
|
-
for (const key in fields) {
|
|
405
|
-
const value = fields[`${key}`]
|
|
406
|
-
newFields[`${key}`] = updateValWithGroup(value, group)
|
|
407
|
-
}
|
|
408
|
-
return newFields
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
function updateValWithGroup(value: Val, group: number): Val {
|
|
412
|
-
if (typeof value === 'string') {
|
|
413
|
-
if (!isValidAddress(value)) return value
|
|
414
|
-
if (isGrouplessAddressWithoutGroupIndex(value)) return `${value}:${group}`
|
|
415
|
-
return value
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
if (Array.isArray(value)) {
|
|
419
|
-
return value.map((v) => updateValWithGroup(v, group))
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (typeof value === 'object') {
|
|
423
|
-
return updateFieldsWithGroup(value as Fields, group)
|
|
424
|
-
}
|
|
425
|
-
return value
|
|
426
|
-
}
|
|
427
|
-
|
|
428
402
|
const scriptFieldRegex = /\{([0-9]*)\}/g
|
|
429
403
|
|
|
430
404
|
export function buildScriptByteCode(
|
package/src/signer/tx-builder.ts
CHANGED
|
@@ -18,7 +18,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
18
18
|
|
|
19
19
|
import { binToHex, hexToBinUnsafe } from '../utils'
|
|
20
20
|
import { fromApiNumber256, node, NodeProvider, toApiNumber256Optional, toApiTokens } from '../api'
|
|
21
|
-
import { addressFromPublicKey, contractIdFromAddress } from '../address'
|
|
21
|
+
import { addressFromPublicKey, contractIdFromAddress, groupOfAddress, isGrouplessAddress } from '../address'
|
|
22
22
|
import { toApiDestinations } from './signer'
|
|
23
23
|
import {
|
|
24
24
|
SignChainedTxParams,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
SignUnsignedTxParams,
|
|
37
37
|
SignUnsignedTxResult,
|
|
38
38
|
BuildTxResult,
|
|
39
|
-
|
|
39
|
+
isGroupedKeyType
|
|
40
40
|
} from './types'
|
|
41
41
|
import { unsignedTxCodec } from '../codec'
|
|
42
42
|
import { groupIndexOfTransaction } from '../transaction'
|
|
@@ -47,6 +47,9 @@ import {
|
|
|
47
47
|
BuildExecuteScriptTxResult,
|
|
48
48
|
BuildTransferTxResult
|
|
49
49
|
} from '../api/api-alephium'
|
|
50
|
+
import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
51
|
+
import { scriptCodec } from '../codec/script-codec'
|
|
52
|
+
import { LockupScript } from '../codec/lockup-script-codec'
|
|
50
53
|
|
|
51
54
|
export abstract class TransactionBuilder {
|
|
52
55
|
abstract get nodeProvider(): NodeProvider
|
|
@@ -204,13 +207,34 @@ export abstract class TransactionBuilder {
|
|
|
204
207
|
}
|
|
205
208
|
}
|
|
206
209
|
|
|
210
|
+
private static checkAndGetParams(params: SignExecuteScriptTxParams): SignExecuteScriptTxParams {
|
|
211
|
+
if (isGroupedKeyType(params.signerKeyType ?? 'default')) {
|
|
212
|
+
return params
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!isGrouplessAddress(params.signerAddress)) {
|
|
216
|
+
throw new Error('Invalid signer key type for groupless address')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const group = params.group ?? getGroupFromTxScript(params.bytecode)
|
|
220
|
+
const defaultGroup = groupOfAddress(params.signerAddress)
|
|
221
|
+
if (group === undefined || group === defaultGroup) {
|
|
222
|
+
return { ...params, group: defaultGroup }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const newBytecode = updateBytecodeWithGroup(params.bytecode, group)
|
|
226
|
+
const newParams = { ...params, bytecode: newBytecode }
|
|
227
|
+
return { ...newParams, group }
|
|
228
|
+
}
|
|
229
|
+
|
|
207
230
|
private buildExecuteScriptTxParams(params: SignExecuteScriptTxParams, publicKey: string): node.BuildExecuteScriptTx {
|
|
208
231
|
TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType)
|
|
209
232
|
|
|
210
|
-
const
|
|
233
|
+
const newParams = TransactionBuilder.checkAndGetParams(params)
|
|
234
|
+
const { signerKeyType, attoAlphAmount, tokens, gasPrice, dustAmount, ...rest } = newParams
|
|
211
235
|
return {
|
|
212
236
|
fromPublicKey: publicKey,
|
|
213
|
-
fromPublicKeyType:
|
|
237
|
+
fromPublicKeyType: signerKeyType,
|
|
214
238
|
attoAlphAmount: toApiNumber256Optional(attoAlphAmount),
|
|
215
239
|
tokens: toApiTokens(tokens),
|
|
216
240
|
gasPrice: toApiNumber256Optional(gasPrice),
|
|
@@ -296,3 +320,47 @@ export abstract class TransactionBuilder {
|
|
|
296
320
|
}
|
|
297
321
|
}
|
|
298
322
|
}
|
|
323
|
+
|
|
324
|
+
export function getGroupFromTxScript(bytecode: string): number | undefined {
|
|
325
|
+
const script = scriptCodec.decode(hexToBinUnsafe(bytecode))
|
|
326
|
+
const instrs = script.methods.flatMap((method) => method.instrs)
|
|
327
|
+
for (let index = 0; index < instrs.length - 1; index += 1) {
|
|
328
|
+
const instr = instrs[`${index}`]
|
|
329
|
+
const nextInstr = instrs[index + 1]
|
|
330
|
+
if (
|
|
331
|
+
instr.name === 'BytesConst' &&
|
|
332
|
+
instr.value.length === 32 &&
|
|
333
|
+
(nextInstr.name === 'CallExternal' || nextInstr.name === 'CallExternalBySelector')
|
|
334
|
+
) {
|
|
335
|
+
const groupIndex = instr.value[instr.value.length - 1]
|
|
336
|
+
if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
|
|
337
|
+
return groupIndex
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
for (const instr of instrs) {
|
|
342
|
+
if (instr.name === 'BytesConst' && instr.value.length === 32) {
|
|
343
|
+
const groupIndex = instr.value[instr.value.length - 1]
|
|
344
|
+
if (groupIndex >= 0 && groupIndex < TOTAL_NUMBER_OF_GROUPS) {
|
|
345
|
+
return groupIndex
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return undefined
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function updateBytecodeWithGroup(bytecode: string, group: number): string {
|
|
353
|
+
const script = scriptCodec.decode(hexToBinUnsafe(bytecode))
|
|
354
|
+
const newMethods = script.methods.map((method) => {
|
|
355
|
+
const newInstrs = method.instrs.map((instr) => {
|
|
356
|
+
if (instr.name === 'AddressConst' && instr.value.kind === 'P2PK') {
|
|
357
|
+
const newLockupScript: LockupScript = { ...instr.value, value: { ...instr.value.value, group } }
|
|
358
|
+
return { ...instr, value: newLockupScript }
|
|
359
|
+
}
|
|
360
|
+
return instr
|
|
361
|
+
})
|
|
362
|
+
return { ...method, instrs: newInstrs }
|
|
363
|
+
})
|
|
364
|
+
const bytes = scriptCodec.encode({ methods: newMethods })
|
|
365
|
+
return binToHex(bytes)
|
|
366
|
+
}
|