@alephium/web3 1.7.1 → 1.7.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/address/address.d.ts +2 -1
- package/dist/src/address/address.js +27 -19
- package/dist/src/contract/contract.d.ts +10 -3
- package/dist/src/contract/contract.js +59 -17
- package/dist/src/signer/tx-builder.d.ts +1 -1
- package/dist/src/signer/tx-builder.js +13 -8
- package/dist/src/transaction/utils.d.ts +2 -0
- package/dist/src/transaction/utils.js +23 -1
- package/dist/src/utils/utils.d.ts +1 -0
- package/dist/src/utils/utils.js +9 -1
- package/package.json +2 -2
- package/src/address/address.ts +24 -18
- package/src/contract/contract.ts +95 -19
- package/src/signer/tx-builder.ts +14 -9
- package/src/transaction/utils.ts +26 -0
- package/src/utils/utils.ts +8 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KeyType } from '../signer';
|
|
2
|
+
import { LockupScript } from '../codec/lockup-script-codec';
|
|
2
3
|
export declare enum AddressType {
|
|
3
4
|
P2PKH = 0,
|
|
4
5
|
P2MPKH = 1,
|
|
@@ -20,4 +21,4 @@ export declare function addressFromContractId(contractId: string): string;
|
|
|
20
21
|
export declare function addressFromTokenId(tokenId: string): string;
|
|
21
22
|
export declare function contractIdFromTx(txId: string, outputIndex: number): string;
|
|
22
23
|
export declare function subContractId(parentContractId: string, pathInHex: string, group: number): string;
|
|
23
|
-
export declare function
|
|
24
|
+
export declare function groupOfLockupScript(lockupScript: LockupScript): number;
|
|
@@ -20,16 +20,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
20
20
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.
|
|
23
|
+
exports.groupOfLockupScript = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromScript = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isContractAddress = exports.isAssetAddress = exports.isValidAddress = exports.validateAddress = exports.AddressType = void 0;
|
|
24
24
|
const elliptic_1 = require("elliptic");
|
|
25
25
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
26
26
|
const constants_1 = require("../constants");
|
|
27
27
|
const blakejs_1 = __importDefault(require("blakejs"));
|
|
28
28
|
const bs58_1 = __importDefault(require("../utils/bs58"));
|
|
29
|
-
const djb2_1 = __importDefault(require("../utils/djb2"));
|
|
30
29
|
const utils_1 = require("../utils");
|
|
31
30
|
const lockup_script_codec_1 = require("../codec/lockup-script-codec");
|
|
32
31
|
const codec_1 = require("../codec");
|
|
32
|
+
const djb2_1 = __importDefault(require("../utils/djb2"));
|
|
33
33
|
const ec = new elliptic_1.ec('secp256k1');
|
|
34
34
|
const PublicKeyHashSize = 32;
|
|
35
35
|
var AddressType;
|
|
@@ -120,23 +120,17 @@ function groupOfAddress(address) {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
exports.groupOfAddress = groupOfAddress;
|
|
123
|
-
function groupOfAddressBytes(bytes) {
|
|
124
|
-
const hint = (0, djb2_1.default)(bytes) | 1;
|
|
125
|
-
const hash = xorByte(hint);
|
|
126
|
-
const group = hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
|
|
127
|
-
return group;
|
|
128
|
-
}
|
|
129
123
|
// Pay to public key hash address
|
|
130
124
|
function groupOfP2pkhAddress(address) {
|
|
131
|
-
return
|
|
125
|
+
return groupFromBytesForAssetAddress(address);
|
|
132
126
|
}
|
|
133
127
|
// Pay to multiple public key hash address
|
|
134
128
|
function groupOfP2mpkhAddress(address) {
|
|
135
|
-
return
|
|
129
|
+
return groupFromBytesForAssetAddress(address.slice(1, 33));
|
|
136
130
|
}
|
|
137
131
|
// Pay to script hash address
|
|
138
132
|
function groupOfP2shAddress(address) {
|
|
139
|
-
return
|
|
133
|
+
return groupFromBytesForAssetAddress(address);
|
|
140
134
|
}
|
|
141
135
|
function contractIdFromAddress(address) {
|
|
142
136
|
return idFromAddress(address);
|
|
@@ -228,11 +222,25 @@ function subContractId(parentContractId, pathInHex, group) {
|
|
|
228
222
|
return (0, utils_1.binToHex)(bytes);
|
|
229
223
|
}
|
|
230
224
|
exports.subContractId = subContractId;
|
|
231
|
-
function
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
225
|
+
function groupOfLockupScript(lockupScript) {
|
|
226
|
+
if (lockupScript.kind === 'P2PKH') {
|
|
227
|
+
return groupFromBytesForAssetAddress(lockupScript.value);
|
|
228
|
+
}
|
|
229
|
+
else if (lockupScript.kind === 'P2MPKH') {
|
|
230
|
+
return groupFromBytesForAssetAddress(lockupScript.value.publicKeyHashes[0]);
|
|
231
|
+
}
|
|
232
|
+
else if (lockupScript.kind === 'P2SH') {
|
|
233
|
+
return groupFromBytesForAssetAddress(lockupScript.value);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// P2C
|
|
237
|
+
const contractId = lockupScript.value;
|
|
238
|
+
return contractId[`${contractId.length - 1}`];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
exports.groupOfLockupScript = groupOfLockupScript;
|
|
242
|
+
function groupFromBytesForAssetAddress(bytes) {
|
|
243
|
+
const hint = (0, djb2_1.default)(bytes) | 1;
|
|
244
|
+
const hash = (0, utils_1.xorByte)(hint);
|
|
245
|
+
return hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
|
|
246
|
+
}
|
|
@@ -121,6 +121,9 @@ export interface ContractState<T extends Fields = Fields> {
|
|
|
121
121
|
fieldsSig: FieldsSig;
|
|
122
122
|
asset: Asset;
|
|
123
123
|
}
|
|
124
|
+
export interface ContractStateWithMaps<T extends Fields = Fields, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>> extends ContractState<T> {
|
|
125
|
+
maps?: M;
|
|
126
|
+
}
|
|
124
127
|
export type TestContractParamsWithoutMaps<F extends Fields = Fields, A extends Arguments = Arguments> = Omit<TestContractParams<F, A>, 'initialMaps'>;
|
|
125
128
|
export interface TestContractParams<F extends Fields = Fields, A extends Arguments = Arguments, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>> {
|
|
126
129
|
group?: number;
|
|
@@ -133,7 +136,7 @@ export interface TestContractParams<F extends Fields = Fields, A extends Argumen
|
|
|
133
136
|
initialMaps?: M;
|
|
134
137
|
initialAsset?: Asset;
|
|
135
138
|
testArgs: A;
|
|
136
|
-
existingContracts?:
|
|
139
|
+
existingContracts?: ContractStateWithMaps[];
|
|
137
140
|
inputAssets?: InputAsset[];
|
|
138
141
|
}
|
|
139
142
|
export interface ContractEvent<T extends Fields = Fields> {
|
|
@@ -152,7 +155,7 @@ export interface TestContractResult<R, M extends Record<string, Map<Val, Val>> =
|
|
|
152
155
|
returns: R;
|
|
153
156
|
gasUsed: number;
|
|
154
157
|
maps?: M;
|
|
155
|
-
contracts:
|
|
158
|
+
contracts: ContractStateWithMaps[];
|
|
156
159
|
txOutputs: Output[];
|
|
157
160
|
events: ContractEvent[];
|
|
158
161
|
debugMessages: DebugMessage[];
|
|
@@ -190,7 +193,7 @@ export declare abstract class ContractFactory<I extends ContractInstance, F exte
|
|
|
190
193
|
abstract at(address: string): I;
|
|
191
194
|
deploy(signer: SignerProvider, deployParams: DeployContractParams<F>): Promise<DeployContractResult<I>>;
|
|
192
195
|
deployTemplate(signer: SignerProvider): Promise<DeployContractResult<I>>;
|
|
193
|
-
|
|
196
|
+
protected stateForTest_(initFields: F, asset?: Asset, address?: string, maps?: Record<string, Map<Val, Val>>): ContractState<F> | ContractStateWithMaps<F>;
|
|
194
197
|
}
|
|
195
198
|
export declare class ExecutableScript<P extends Fields = Fields, R extends Val | null = null> {
|
|
196
199
|
readonly script: Script;
|
|
@@ -266,6 +269,10 @@ export declare function subscribeEventsFromContract<T extends Fields, M extends
|
|
|
266
269
|
export declare function addStdIdToFields<F extends Fields>(contract: Contract, fields: F): F | (F & {
|
|
267
270
|
__stdInterfaceId: HexString;
|
|
268
271
|
});
|
|
272
|
+
export declare function extractMapsFromApiResult(selfAddress: string, params: Optional<TestContractParams, 'testArgs' | 'initialFields'>, group: number, apiResult: node.TestContractResult, getContractByCodeHash: (codeHash: string) => Contract): {
|
|
273
|
+
address: string;
|
|
274
|
+
maps: Record<string, Map<Val, Val>>;
|
|
275
|
+
}[];
|
|
269
276
|
export declare function testMethod<I extends ContractInstance, F extends Fields, A extends Arguments, R, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>>(factory: ContractFactory<I, F>, methodName: string, params: Optional<TestContractParams<F, A, M>, 'testArgs' | 'initialFields'>, getContractByCodeHash: (codeHash: string) => Contract): Promise<TestContractResult<R, M>>;
|
|
270
277
|
export declare class RalphMap<K extends Val, V extends Val> {
|
|
271
278
|
private readonly parentContract;
|
|
@@ -40,7 +40,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
40
40
|
return result;
|
|
41
41
|
};
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
-
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.testMethod = 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;
|
|
43
|
+
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.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
46
|
const ralph = __importStar(require("./ralph"));
|
|
@@ -672,12 +672,18 @@ class ContractFactory {
|
|
|
672
672
|
});
|
|
673
673
|
}
|
|
674
674
|
// This is used for testing contract functions
|
|
675
|
-
|
|
675
|
+
stateForTest_(initFields, asset, address, maps) {
|
|
676
676
|
const newAsset = {
|
|
677
|
-
alphAmount: asset?.alphAmount ?? constants_1.
|
|
677
|
+
alphAmount: asset?.alphAmount ?? constants_1.MINIMAL_CONTRACT_DEPOSIT,
|
|
678
678
|
tokens: asset?.tokens
|
|
679
679
|
};
|
|
680
|
-
|
|
680
|
+
const state = this.contract.toState(addStdIdToFields(this.contract, initFields), newAsset, address);
|
|
681
|
+
return {
|
|
682
|
+
...state,
|
|
683
|
+
bytecode: this.contract.bytecodeDebug,
|
|
684
|
+
codeHash: this.contract.codeHash,
|
|
685
|
+
maps: maps
|
|
686
|
+
};
|
|
681
687
|
}
|
|
682
688
|
}
|
|
683
689
|
exports.ContractFactory = ContractFactory;
|
|
@@ -875,29 +881,65 @@ function mapsToExistingContracts(contract, parentContractId, group, initialMaps)
|
|
|
875
881
|
});
|
|
876
882
|
return contractStates;
|
|
877
883
|
}
|
|
884
|
+
function hasMap(state) {
|
|
885
|
+
return state.maps !== undefined;
|
|
886
|
+
}
|
|
887
|
+
function getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash) {
|
|
888
|
+
const selfMaps = params.initialMaps ?? {};
|
|
889
|
+
const selfMapEntries = mapsToExistingContracts(selfContract, selfContractId, group, selfMaps);
|
|
890
|
+
const existingContracts = params.existingContracts ?? [];
|
|
891
|
+
const existingMapEntries = existingContracts.flatMap((contractState) => {
|
|
892
|
+
return hasMap(contractState)
|
|
893
|
+
? mapsToExistingContracts(getContractByCodeHash(contractState.codeHash), contractState.contractId, group, contractState.maps ?? {})
|
|
894
|
+
: [];
|
|
895
|
+
});
|
|
896
|
+
return existingContracts.concat(selfMapEntries, existingMapEntries);
|
|
897
|
+
}
|
|
898
|
+
function extractMapsFromApiResult(selfAddress, params, group, apiResult, getContractByCodeHash) {
|
|
899
|
+
const selfMaps = params.initialMaps ?? {};
|
|
900
|
+
const existingContracts = params.existingContracts ?? [];
|
|
901
|
+
const filtered = apiResult.contracts.filter((c) => c.address === selfAddress || existingContracts.find((s) => s.address === c.address) !== undefined);
|
|
902
|
+
const allMaps = [];
|
|
903
|
+
filtered.forEach((state) => {
|
|
904
|
+
const artifact = getContractByCodeHash(state.codeHash);
|
|
905
|
+
if (artifact.mapsSig !== undefined) {
|
|
906
|
+
const originMaps = state.address === selfAddress
|
|
907
|
+
? selfMaps
|
|
908
|
+
: existingContracts.find((s) => s.address === state.address).maps;
|
|
909
|
+
const maps = existingContractsToMaps(artifact, state.address, group, apiResult, originMaps ?? {});
|
|
910
|
+
allMaps.push({ address: state.address, maps });
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
return allMaps;
|
|
914
|
+
}
|
|
915
|
+
exports.extractMapsFromApiResult = extractMapsFromApiResult;
|
|
878
916
|
async function testMethod(factory, methodName, params, getContractByCodeHash) {
|
|
879
917
|
const txId = params?.txId ?? randomTxId();
|
|
880
|
-
const
|
|
881
|
-
const
|
|
882
|
-
const
|
|
918
|
+
const selfContract = factory.contract;
|
|
919
|
+
const selfAddress = params.address ?? (0, address_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
|
|
920
|
+
const selfContractId = (0, utils_1.binToHex)((0, address_1.contractIdFromAddress)(selfAddress));
|
|
883
921
|
const group = params.group ?? 0;
|
|
884
|
-
const
|
|
885
|
-
const
|
|
886
|
-
const apiParams = contract.toApiTestContractParams(methodName, {
|
|
922
|
+
const existingContracts = getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash);
|
|
923
|
+
const apiParams = selfContract.toApiTestContractParams(methodName, {
|
|
887
924
|
...params,
|
|
888
|
-
address,
|
|
925
|
+
address: selfAddress,
|
|
889
926
|
txId: txId,
|
|
890
|
-
initialFields: addStdIdToFields(
|
|
927
|
+
initialFields: addStdIdToFields(selfContract, params.initialFields ?? {}),
|
|
891
928
|
testArgs: params.testArgs === undefined ? {} : params.testArgs,
|
|
892
|
-
existingContracts
|
|
929
|
+
existingContracts
|
|
893
930
|
});
|
|
894
931
|
const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
|
|
895
|
-
const
|
|
896
|
-
const testResult =
|
|
897
|
-
|
|
932
|
+
const allMaps = extractMapsFromApiResult(selfAddress, params, group, apiResult, getContractByCodeHash);
|
|
933
|
+
const testResult = selfContract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash);
|
|
934
|
+
testResult.contracts.forEach((c) => {
|
|
935
|
+
const maps = allMaps.find((v) => v.address === c.address)?.maps;
|
|
936
|
+
if (maps !== undefined)
|
|
937
|
+
c['maps'] = maps;
|
|
938
|
+
});
|
|
939
|
+
selfContract.printDebugMessages(methodName, testResult.debugMessages);
|
|
898
940
|
return {
|
|
899
941
|
...testResult,
|
|
900
|
-
maps
|
|
942
|
+
maps: allMaps.find((v) => v.address === selfAddress)?.maps
|
|
901
943
|
};
|
|
902
944
|
}
|
|
903
945
|
exports.testMethod = testMethod;
|
|
@@ -8,5 +8,5 @@ export declare abstract class TransactionBuilder {
|
|
|
8
8
|
buildTransferTx(params: SignTransferTxParams, publicKey: string): Promise<Omit<SignTransferTxResult, 'signature'>>;
|
|
9
9
|
buildDeployContractTx(params: SignDeployContractTxParams, publicKey: string): Promise<Omit<SignDeployContractTxResult, 'signature'>>;
|
|
10
10
|
buildExecuteScriptTx(params: SignExecuteScriptTxParams, publicKey: string): Promise<Omit<SignExecuteScriptTxResult, 'signature'>>;
|
|
11
|
-
buildUnsignedTx(params: SignUnsignedTxParams):
|
|
11
|
+
buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'>;
|
|
12
12
|
}
|
|
@@ -22,6 +22,9 @@ 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 codec_1 = require("../codec");
|
|
26
|
+
const transaction_1 = require("../transaction");
|
|
27
|
+
const hash_1 = require("../codec/hash");
|
|
25
28
|
class TransactionBuilder {
|
|
26
29
|
static from(param0, param1, customFetch) {
|
|
27
30
|
const nodeProvider = typeof param0 === 'string' ? new api_1.NodeProvider(param0, param1, customFetch) : param0;
|
|
@@ -80,16 +83,18 @@ class TransactionBuilder {
|
|
|
80
83
|
const response = await this.nodeProvider.contracts.postContractsUnsignedTxExecuteScript(data);
|
|
81
84
|
return { ...response, groupIndex: response.fromGroup, gasPrice: (0, api_1.fromApiNumber256)(response.gasPrice) };
|
|
82
85
|
}
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
const decoded =
|
|
86
|
+
buildUnsignedTx(params) {
|
|
87
|
+
const unsignedTxBin = (0, utils_1.hexToBinUnsafe)(params.unsignedTx);
|
|
88
|
+
const decoded = codec_1.unsignedTxCodec.decode(unsignedTxBin);
|
|
89
|
+
const txId = (0, utils_1.binToHex)((0, hash_1.blakeHash)(unsignedTxBin));
|
|
90
|
+
const [fromGroup, toGroup] = (0, transaction_1.groupIndexOfTransaction)(decoded);
|
|
86
91
|
return {
|
|
87
|
-
fromGroup:
|
|
88
|
-
toGroup:
|
|
92
|
+
fromGroup: fromGroup,
|
|
93
|
+
toGroup: toGroup,
|
|
89
94
|
unsignedTx: params.unsignedTx,
|
|
90
|
-
txId:
|
|
91
|
-
gasAmount: decoded.
|
|
92
|
-
gasPrice:
|
|
95
|
+
txId: txId,
|
|
96
|
+
gasAmount: decoded.gasAmount,
|
|
97
|
+
gasPrice: decoded.gasPrice
|
|
93
98
|
};
|
|
94
99
|
}
|
|
95
100
|
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { node } from '../api';
|
|
2
|
+
import { UnsignedTx } from '../codec';
|
|
2
3
|
export declare function waitForTxConfirmation(txId: string, confirmations: number, requestInterval: number): Promise<node.Confirmed>;
|
|
4
|
+
export declare function groupIndexOfTransaction(unsignedTx: UnsignedTx): [number, number];
|
|
@@ -17,8 +17,11 @@ 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.waitForTxConfirmation = void 0;
|
|
20
|
+
exports.groupIndexOfTransaction = exports.waitForTxConfirmation = void 0;
|
|
21
|
+
const address_1 = require("../address");
|
|
22
|
+
const constants_1 = require("../constants");
|
|
21
23
|
const global_1 = require("../global");
|
|
24
|
+
const utils_1 = require("../utils");
|
|
22
25
|
function isConfirmed(txStatus) {
|
|
23
26
|
return txStatus.type === 'Confirmed';
|
|
24
27
|
}
|
|
@@ -32,3 +35,22 @@ async function waitForTxConfirmation(txId, confirmations, requestInterval) {
|
|
|
32
35
|
return waitForTxConfirmation(txId, confirmations, requestInterval);
|
|
33
36
|
}
|
|
34
37
|
exports.waitForTxConfirmation = waitForTxConfirmation;
|
|
38
|
+
function groupIndexOfTransaction(unsignedTx) {
|
|
39
|
+
if (unsignedTx.inputs.length === 0)
|
|
40
|
+
throw new Error('Empty inputs for unsignedTx');
|
|
41
|
+
const fromGroup = groupFromHint(unsignedTx.inputs[0].hint);
|
|
42
|
+
let toGroup = fromGroup;
|
|
43
|
+
for (const output of unsignedTx.fixedOutputs) {
|
|
44
|
+
const outputGroup = (0, address_1.groupOfLockupScript)(output.lockupScript);
|
|
45
|
+
if (outputGroup !== fromGroup) {
|
|
46
|
+
toGroup = outputGroup;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return [fromGroup, toGroup];
|
|
51
|
+
}
|
|
52
|
+
exports.groupIndexOfTransaction = groupIndexOfTransaction;
|
|
53
|
+
function groupFromHint(hint) {
|
|
54
|
+
const hash = (0, utils_1.xorByte)(hint);
|
|
55
|
+
return hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
|
|
56
|
+
}
|
|
@@ -24,6 +24,7 @@ export declare function isDevnet(networkId?: number): boolean;
|
|
|
24
24
|
export declare function targetToDifficulty(compactedTarget: HexString): bigint;
|
|
25
25
|
export declare function difficultyToTarget(diff: bigint): HexString;
|
|
26
26
|
export declare function concatBytes(arrays: Uint8Array[]): Uint8Array;
|
|
27
|
+
export declare function xorByte(intValue: number): number;
|
|
27
28
|
type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
|
|
28
29
|
export type Eq<X, Y> = _Eq<{
|
|
29
30
|
[P in keyof X]: X[P];
|
package/dist/src/utils/utils.js
CHANGED
|
@@ -20,7 +20,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
20
20
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.assertType = exports.concatBytes = exports.difficultyToTarget = exports.targetToDifficulty = exports.isDevnet = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.binToHex = exports.hexToBinUnsafe = exports.toNonNegativeBigInt = exports.isHexString = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
|
|
23
|
+
exports.assertType = exports.xorByte = exports.concatBytes = exports.difficultyToTarget = exports.targetToDifficulty = exports.isDevnet = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.binToHex = exports.hexToBinUnsafe = exports.toNonNegativeBigInt = exports.isHexString = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
|
|
24
24
|
const elliptic_1 = require("elliptic");
|
|
25
25
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
26
26
|
const constants_1 = require("../constants");
|
|
@@ -153,6 +153,14 @@ function concatBytes(arrays) {
|
|
|
153
153
|
return result;
|
|
154
154
|
}
|
|
155
155
|
exports.concatBytes = concatBytes;
|
|
156
|
+
function xorByte(intValue) {
|
|
157
|
+
const byte0 = (intValue >> 24) & 0xff;
|
|
158
|
+
const byte1 = (intValue >> 16) & 0xff;
|
|
159
|
+
const byte2 = (intValue >> 8) & 0xff;
|
|
160
|
+
const byte3 = intValue & 0xff;
|
|
161
|
+
return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff;
|
|
162
|
+
}
|
|
163
|
+
exports.xorByte = xorByte;
|
|
156
164
|
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
|
|
157
165
|
function assertType() { }
|
|
158
166
|
exports.assertType = assertType;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alephium/web3",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
4
4
|
"description": "A JS/TS library to interact with the Alephium platform",
|
|
5
5
|
"license": "GPL",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"ts-node": "^10.9.1",
|
|
84
84
|
"tslib": "^2.5.0",
|
|
85
85
|
"typescript": "^4.9.5",
|
|
86
|
-
"webpack": "^5.
|
|
86
|
+
"webpack": "^5.94.0",
|
|
87
87
|
"webpack-cli": "^4.10.0"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|
package/src/address/address.ts
CHANGED
|
@@ -21,11 +21,12 @@ import BN from 'bn.js'
|
|
|
21
21
|
import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
22
22
|
import blake from 'blakejs'
|
|
23
23
|
import bs58 from '../utils/bs58'
|
|
24
|
-
import
|
|
25
|
-
import { binToHex, concatBytes, hexToBinUnsafe, isHexString } from '../utils'
|
|
24
|
+
import { binToHex, concatBytes, hexToBinUnsafe, isHexString, xorByte } from '../utils'
|
|
26
25
|
import { KeyType } from '../signer'
|
|
27
26
|
import { P2MPKH, lockupScriptCodec } from '../codec/lockup-script-codec'
|
|
28
27
|
import { i32Codec } from '../codec'
|
|
28
|
+
import { LockupScript } from '../codec/lockup-script-codec'
|
|
29
|
+
import djb2 from '../utils/djb2'
|
|
29
30
|
|
|
30
31
|
const ec = new EC('secp256k1')
|
|
31
32
|
const PublicKeyHashSize = 32
|
|
@@ -112,26 +113,19 @@ export function groupOfAddress(address: string): number {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
function groupOfAddressBytes(bytes: Uint8Array): number {
|
|
116
|
-
const hint = djb2(bytes) | 1
|
|
117
|
-
const hash = xorByte(hint)
|
|
118
|
-
const group = hash % TOTAL_NUMBER_OF_GROUPS
|
|
119
|
-
return group
|
|
120
|
-
}
|
|
121
|
-
|
|
122
116
|
// Pay to public key hash address
|
|
123
117
|
function groupOfP2pkhAddress(address: Uint8Array): number {
|
|
124
|
-
return
|
|
118
|
+
return groupFromBytesForAssetAddress(address)
|
|
125
119
|
}
|
|
126
120
|
|
|
127
121
|
// Pay to multiple public key hash address
|
|
128
122
|
function groupOfP2mpkhAddress(address: Uint8Array): number {
|
|
129
|
-
return
|
|
123
|
+
return groupFromBytesForAssetAddress(address.slice(1, 33))
|
|
130
124
|
}
|
|
131
125
|
|
|
132
126
|
// Pay to script hash address
|
|
133
127
|
function groupOfP2shAddress(address: Uint8Array): number {
|
|
134
|
-
return
|
|
128
|
+
return groupFromBytesForAssetAddress(address)
|
|
135
129
|
}
|
|
136
130
|
|
|
137
131
|
export function contractIdFromAddress(address: string): Uint8Array {
|
|
@@ -225,10 +219,22 @@ export function subContractId(parentContractId: string, pathInHex: string, group
|
|
|
225
219
|
return binToHex(bytes)
|
|
226
220
|
}
|
|
227
221
|
|
|
228
|
-
export function
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
222
|
+
export function groupOfLockupScript(lockupScript: LockupScript): number {
|
|
223
|
+
if (lockupScript.kind === 'P2PKH') {
|
|
224
|
+
return groupFromBytesForAssetAddress(lockupScript.value)
|
|
225
|
+
} else if (lockupScript.kind === 'P2MPKH') {
|
|
226
|
+
return groupFromBytesForAssetAddress(lockupScript.value.publicKeyHashes[0])
|
|
227
|
+
} else if (lockupScript.kind === 'P2SH') {
|
|
228
|
+
return groupFromBytesForAssetAddress(lockupScript.value)
|
|
229
|
+
} else {
|
|
230
|
+
// P2C
|
|
231
|
+
const contractId = lockupScript.value
|
|
232
|
+
return contractId[`${contractId.length - 1}`]
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function groupFromBytesForAssetAddress(bytes: Uint8Array): number {
|
|
237
|
+
const hint = djb2(bytes) | 1
|
|
238
|
+
const hash = xorByte(hint)
|
|
239
|
+
return hash % TOTAL_NUMBER_OF_GROUPS
|
|
234
240
|
}
|
package/src/contract/contract.ts
CHANGED
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
import { contractIdFromAddress, groupOfAddress, addressFromContractId, subContractId } from '../address'
|
|
60
60
|
import { getCurrentNodeProvider } from '../global'
|
|
61
61
|
import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
|
|
62
|
-
import { ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
62
|
+
import { MINIMAL_CONTRACT_DEPOSIT, ONE_ALPH, TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
63
63
|
import * as blake from 'blakejs'
|
|
64
64
|
import { isContractDebugMessageEnabled } from '../debug'
|
|
65
65
|
import {
|
|
@@ -885,6 +885,13 @@ export interface ContractState<T extends Fields = Fields> {
|
|
|
885
885
|
asset: Asset
|
|
886
886
|
}
|
|
887
887
|
|
|
888
|
+
export interface ContractStateWithMaps<
|
|
889
|
+
T extends Fields = Fields,
|
|
890
|
+
M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>
|
|
891
|
+
> extends ContractState<T> {
|
|
892
|
+
maps?: M
|
|
893
|
+
}
|
|
894
|
+
|
|
888
895
|
function toApiContractState(state: ContractState, structs: Struct[]): node.ContractState {
|
|
889
896
|
const stateFields = state.fields ?? {}
|
|
890
897
|
const fieldsSig = state.fieldsSig
|
|
@@ -942,7 +949,7 @@ export interface TestContractParams<
|
|
|
942
949
|
initialMaps?: M
|
|
943
950
|
initialAsset?: Asset // default 1 ALPH
|
|
944
951
|
testArgs: A
|
|
945
|
-
existingContracts?:
|
|
952
|
+
existingContracts?: ContractStateWithMaps[] // default no existing contracts
|
|
946
953
|
inputAssets?: InputAsset[] // default no input asserts
|
|
947
954
|
}
|
|
948
955
|
|
|
@@ -965,7 +972,7 @@ export interface TestContractResult<R, M extends Record<string, Map<Val, Val>> =
|
|
|
965
972
|
returns: R
|
|
966
973
|
gasUsed: number
|
|
967
974
|
maps?: M
|
|
968
|
-
contracts:
|
|
975
|
+
contracts: ContractStateWithMaps[]
|
|
969
976
|
txOutputs: Output[]
|
|
970
977
|
events: ContractEvent[]
|
|
971
978
|
debugMessages: DebugMessage[]
|
|
@@ -1065,12 +1072,23 @@ export abstract class ContractFactory<I extends ContractInstance, F extends Fiel
|
|
|
1065
1072
|
}
|
|
1066
1073
|
|
|
1067
1074
|
// This is used for testing contract functions
|
|
1068
|
-
|
|
1075
|
+
protected stateForTest_(
|
|
1076
|
+
initFields: F,
|
|
1077
|
+
asset?: Asset,
|
|
1078
|
+
address?: string,
|
|
1079
|
+
maps?: Record<string, Map<Val, Val>>
|
|
1080
|
+
): ContractState<F> | ContractStateWithMaps<F> {
|
|
1069
1081
|
const newAsset = {
|
|
1070
|
-
alphAmount: asset?.alphAmount ??
|
|
1082
|
+
alphAmount: asset?.alphAmount ?? MINIMAL_CONTRACT_DEPOSIT,
|
|
1071
1083
|
tokens: asset?.tokens
|
|
1072
1084
|
}
|
|
1073
|
-
|
|
1085
|
+
const state = this.contract.toState(addStdIdToFields(this.contract, initFields), newAsset, address)
|
|
1086
|
+
return {
|
|
1087
|
+
...state,
|
|
1088
|
+
bytecode: this.contract.bytecodeDebug,
|
|
1089
|
+
codeHash: this.contract.codeHash,
|
|
1090
|
+
maps: maps
|
|
1091
|
+
}
|
|
1074
1092
|
}
|
|
1075
1093
|
}
|
|
1076
1094
|
|
|
@@ -1381,6 +1399,60 @@ function mapsToExistingContracts(
|
|
|
1381
1399
|
return contractStates
|
|
1382
1400
|
}
|
|
1383
1401
|
|
|
1402
|
+
function hasMap(state: ContractState): state is ContractStateWithMaps {
|
|
1403
|
+
return (state as ContractStateWithMaps).maps !== undefined
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
function getTestExistingContracts(
|
|
1407
|
+
selfContract: Contract,
|
|
1408
|
+
selfContractId: string,
|
|
1409
|
+
group: number,
|
|
1410
|
+
params: Optional<TestContractParams, 'testArgs' | 'initialFields'>,
|
|
1411
|
+
getContractByCodeHash: (codeHash: string) => Contract
|
|
1412
|
+
): ContractState[] {
|
|
1413
|
+
const selfMaps = params.initialMaps ?? {}
|
|
1414
|
+
const selfMapEntries = mapsToExistingContracts(selfContract, selfContractId, group, selfMaps)
|
|
1415
|
+
const existingContracts = params.existingContracts ?? []
|
|
1416
|
+
const existingMapEntries = existingContracts.flatMap((contractState) => {
|
|
1417
|
+
return hasMap(contractState)
|
|
1418
|
+
? mapsToExistingContracts(
|
|
1419
|
+
getContractByCodeHash(contractState.codeHash),
|
|
1420
|
+
contractState.contractId,
|
|
1421
|
+
group,
|
|
1422
|
+
contractState.maps ?? {}
|
|
1423
|
+
)
|
|
1424
|
+
: []
|
|
1425
|
+
})
|
|
1426
|
+
return existingContracts.concat(selfMapEntries, existingMapEntries)
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
export function extractMapsFromApiResult(
|
|
1430
|
+
selfAddress: string,
|
|
1431
|
+
params: Optional<TestContractParams, 'testArgs' | 'initialFields'>,
|
|
1432
|
+
group: number,
|
|
1433
|
+
apiResult: node.TestContractResult,
|
|
1434
|
+
getContractByCodeHash: (codeHash: string) => Contract
|
|
1435
|
+
): { address: string; maps: Record<string, Map<Val, Val>> }[] {
|
|
1436
|
+
const selfMaps = params.initialMaps ?? {}
|
|
1437
|
+
const existingContracts = params.existingContracts ?? []
|
|
1438
|
+
const filtered = apiResult.contracts.filter(
|
|
1439
|
+
(c) => c.address === selfAddress || existingContracts.find((s) => s.address === c.address) !== undefined
|
|
1440
|
+
)
|
|
1441
|
+
const allMaps: { address: string; maps: Record<string, Map<Val, Val>> }[] = []
|
|
1442
|
+
filtered.forEach((state) => {
|
|
1443
|
+
const artifact = getContractByCodeHash(state.codeHash)
|
|
1444
|
+
if (artifact.mapsSig !== undefined) {
|
|
1445
|
+
const originMaps =
|
|
1446
|
+
state.address === selfAddress
|
|
1447
|
+
? selfMaps
|
|
1448
|
+
: (existingContracts.find((s) => s.address === state.address) as ContractStateWithMaps).maps
|
|
1449
|
+
const maps = existingContractsToMaps(artifact, state.address, group, apiResult, originMaps ?? {})
|
|
1450
|
+
allMaps.push({ address: state.address, maps })
|
|
1451
|
+
}
|
|
1452
|
+
})
|
|
1453
|
+
return allMaps
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1384
1456
|
export async function testMethod<
|
|
1385
1457
|
I extends ContractInstance,
|
|
1386
1458
|
F extends Fields,
|
|
@@ -1394,27 +1466,31 @@ export async function testMethod<
|
|
|
1394
1466
|
getContractByCodeHash: (codeHash: string) => Contract
|
|
1395
1467
|
): Promise<TestContractResult<R, M>> {
|
|
1396
1468
|
const txId = params?.txId ?? randomTxId()
|
|
1397
|
-
const
|
|
1398
|
-
const
|
|
1399
|
-
const
|
|
1469
|
+
const selfContract = factory.contract
|
|
1470
|
+
const selfAddress = params.address ?? addressFromContractId(binToHex(crypto.getRandomValues(new Uint8Array(32))))
|
|
1471
|
+
const selfContractId = binToHex(contractIdFromAddress(selfAddress))
|
|
1400
1472
|
const group = params.group ?? 0
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
const apiParams =
|
|
1473
|
+
const existingContracts = getTestExistingContracts(selfContract, selfContractId, group, params, getContractByCodeHash)
|
|
1474
|
+
|
|
1475
|
+
const apiParams = selfContract.toApiTestContractParams(methodName, {
|
|
1404
1476
|
...params,
|
|
1405
|
-
address,
|
|
1477
|
+
address: selfAddress,
|
|
1406
1478
|
txId: txId,
|
|
1407
|
-
initialFields: addStdIdToFields(
|
|
1479
|
+
initialFields: addStdIdToFields(selfContract, params.initialFields ?? {}),
|
|
1408
1480
|
testArgs: params.testArgs === undefined ? {} : params.testArgs,
|
|
1409
|
-
existingContracts
|
|
1481
|
+
existingContracts
|
|
1410
1482
|
})
|
|
1411
1483
|
const apiResult = await getCurrentNodeProvider().contracts.postContractsTestContract(apiParams)
|
|
1412
|
-
const
|
|
1413
|
-
const testResult =
|
|
1414
|
-
|
|
1484
|
+
const allMaps = extractMapsFromApiResult(selfAddress, params, group, apiResult, getContractByCodeHash)
|
|
1485
|
+
const testResult = selfContract.fromApiTestContractResult(methodName, apiResult, txId, getContractByCodeHash)
|
|
1486
|
+
testResult.contracts.forEach((c) => {
|
|
1487
|
+
const maps = allMaps.find((v) => v.address === c.address)?.maps
|
|
1488
|
+
if (maps !== undefined) c['maps'] = maps
|
|
1489
|
+
})
|
|
1490
|
+
selfContract.printDebugMessages(methodName, testResult.debugMessages)
|
|
1415
1491
|
return {
|
|
1416
1492
|
...testResult,
|
|
1417
|
-
maps
|
|
1493
|
+
maps: allMaps.find((v) => v.address === selfAddress)?.maps
|
|
1418
1494
|
} as TestContractResult<R, M>
|
|
1419
1495
|
}
|
|
1420
1496
|
|