@alephium/web3 1.12.0-beta.0 → 1.12.0-danube.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/address/address.d.ts +1 -0
- package/dist/src/address/address.js +45 -22
- package/dist/src/api/api-alephium.d.ts +78 -124
- package/dist/src/api/api-alephium.js +0 -50
- package/dist/src/api/node-provider.d.ts +0 -2
- package/dist/src/api/node-provider.js +0 -1
- package/dist/src/codec/instr-codec.d.ts +26 -10
- package/dist/src/codec/instr-codec.js +38 -18
- package/dist/src/contract/contract.d.ts +11 -6
- package/dist/src/contract/contract.js +35 -21
- package/dist/src/contract/deployment.d.ts +2 -0
- package/dist/src/signer/signer.d.ts +13 -13
- package/dist/src/signer/signer.js +84 -9
- package/dist/src/signer/tx-builder.d.ts +4 -10
- package/dist/src/signer/tx-builder.js +41 -67
- package/dist/src/signer/types.d.ts +14 -27
- package/dist/src/signer/types.js +0 -3
- package/dist/src/utils/sign.js +2 -2
- package/package.json +1 -1
- package/src/address/address.ts +50 -19
- package/src/api/api-alephium.ts +92 -172
- package/src/api/node-provider.ts +0 -3
- package/src/codec/instr-codec.ts +45 -21
- package/src/contract/contract.ts +45 -29
- package/src/contract/deployment.ts +2 -0
- package/src/signer/signer.ts +118 -24
- package/src/signer/tx-builder.ts +60 -99
- package/src/signer/types.ts +31 -39
- package/src/utils/sign.ts +2 -2
|
@@ -109,42 +109,6 @@ class TransactionBuilder {
|
|
|
109
109
|
});
|
|
110
110
|
return results;
|
|
111
111
|
}
|
|
112
|
-
async buildGrouplessTransferTx(params) {
|
|
113
|
-
const data = this.buildGrouplessTransferTxParams(params);
|
|
114
|
-
const response = await this.nodeProvider.groupless.postGrouplessTransfer(data);
|
|
115
|
-
return response.map((result) => {
|
|
116
|
-
return {
|
|
117
|
-
...this.convertTransferTxResult(result),
|
|
118
|
-
type: 'Transfer'
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
async buildGrouplessDeployContractTx(params) {
|
|
123
|
-
const data = this.buildGrouplessDeployContractTxParams(params);
|
|
124
|
-
const response = await this.nodeProvider.groupless.postGrouplessDeployContract(data);
|
|
125
|
-
const transferTxs = response.transferTxs.map((result) => ({
|
|
126
|
-
...this.convertTransferTxResult(result),
|
|
127
|
-
type: 'Transfer'
|
|
128
|
-
}));
|
|
129
|
-
const deployContractTx = {
|
|
130
|
-
...this.convertDeployContractTxResult(response.deployContractTx),
|
|
131
|
-
type: 'DeployContract'
|
|
132
|
-
};
|
|
133
|
-
return [...transferTxs, deployContractTx];
|
|
134
|
-
}
|
|
135
|
-
async buildGrouplessExecuteScriptTx(params) {
|
|
136
|
-
const data = this.buildGrouplessExecuteScriptTxParams(params);
|
|
137
|
-
const response = await this.nodeProvider.groupless.postGrouplessExecuteScript(data);
|
|
138
|
-
const transferTxs = response.transferTxs.map((result) => ({
|
|
139
|
-
...this.convertTransferTxResult(result),
|
|
140
|
-
type: 'Transfer'
|
|
141
|
-
}));
|
|
142
|
-
const executeScriptTx = {
|
|
143
|
-
...this.convertExecuteScriptTxResult(response.executeScriptTx),
|
|
144
|
-
type: 'ExecuteScript'
|
|
145
|
-
};
|
|
146
|
-
return [...transferTxs, executeScriptTx];
|
|
147
|
-
}
|
|
148
112
|
static buildUnsignedTx(params) {
|
|
149
113
|
const unsignedTxBin = (0, utils_1.hexToBinUnsafe)(params.unsignedTx);
|
|
150
114
|
const decoded = codec_1.unsignedTxCodec.decode(unsignedTxBin);
|
|
@@ -170,37 +134,6 @@ class TransactionBuilder {
|
|
|
170
134
|
...rest
|
|
171
135
|
};
|
|
172
136
|
}
|
|
173
|
-
buildGrouplessTransferTxParams(params) {
|
|
174
|
-
return {
|
|
175
|
-
fromAddress: params.fromAddress,
|
|
176
|
-
destinations: (0, signer_1.toApiDestinations)(params.destinations),
|
|
177
|
-
gasPrice: (0, api_1.toApiNumber256Optional)(params.gasPrice),
|
|
178
|
-
targetBlockHash: params.targetBlockHash
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
buildGrouplessDeployContractTxParams(params) {
|
|
182
|
-
return {
|
|
183
|
-
fromAddress: params.fromAddress,
|
|
184
|
-
bytecode: params.bytecode,
|
|
185
|
-
initialAttoAlphAmount: (0, api_1.toApiNumber256Optional)(params.initialAttoAlphAmount),
|
|
186
|
-
initialTokenAmounts: (0, api_1.toApiTokens)(params.initialTokenAmounts),
|
|
187
|
-
issueTokenAmount: (0, api_1.toApiNumber256Optional)(params.issueTokenAmount),
|
|
188
|
-
issueTokenTo: params.issueTokenTo,
|
|
189
|
-
gasPrice: (0, api_1.toApiNumber256Optional)(params.gasPrice),
|
|
190
|
-
targetBlockHash: params.targetBlockHash
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
buildGrouplessExecuteScriptTxParams(params) {
|
|
194
|
-
return {
|
|
195
|
-
fromAddress: params.fromAddress,
|
|
196
|
-
bytecode: params.bytecode,
|
|
197
|
-
attoAlphAmount: (0, api_1.toApiNumber256Optional)(params.attoAlphAmount),
|
|
198
|
-
tokens: (0, api_1.toApiTokens)(params.tokens),
|
|
199
|
-
gasPrice: (0, api_1.toApiNumber256Optional)(params.gasPrice),
|
|
200
|
-
targetBlockHash: params.targetBlockHash,
|
|
201
|
-
gasEstimationMultiplier: params.gasEstimationMultiplier
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
137
|
buildDeployContractTxParams(params, publicKey) {
|
|
205
138
|
TransactionBuilder.validatePublicKey(params, publicKey, params.signerKeyType);
|
|
206
139
|
const { initialAttoAlphAmount, initialTokenAmounts, issueTokenAmount, gasPrice, ...rest } = params;
|
|
@@ -227,12 +160,40 @@ class TransactionBuilder {
|
|
|
227
160
|
};
|
|
228
161
|
}
|
|
229
162
|
convertTransferTxResult(result) {
|
|
163
|
+
// BuildGrouplessTransferTxResult
|
|
164
|
+
if ('transferTxs' in result) {
|
|
165
|
+
return {
|
|
166
|
+
transferTxs: result.transferTxs.map((r) => ({
|
|
167
|
+
...r,
|
|
168
|
+
gasPrice: (0, api_1.fromApiNumber256)(r.gasPrice)
|
|
169
|
+
})),
|
|
170
|
+
tx: {
|
|
171
|
+
...result.transferTx,
|
|
172
|
+
gasPrice: (0, api_1.fromApiNumber256)(result.transferTx.gasPrice)
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
230
176
|
return {
|
|
231
177
|
...result,
|
|
232
178
|
gasPrice: (0, api_1.fromApiNumber256)(result.gasPrice)
|
|
233
179
|
};
|
|
234
180
|
}
|
|
235
181
|
convertDeployContractTxResult(result) {
|
|
182
|
+
if ('transferTxs' in result) {
|
|
183
|
+
const contractId = (0, utils_1.binToHex)((0, address_1.contractIdFromAddress)(result.deployContractTx.contractAddress));
|
|
184
|
+
return {
|
|
185
|
+
transferTxs: result.transferTxs.map((r) => ({
|
|
186
|
+
...r,
|
|
187
|
+
gasPrice: (0, api_1.fromApiNumber256)(r.gasPrice)
|
|
188
|
+
})),
|
|
189
|
+
tx: {
|
|
190
|
+
...result.deployContractTx,
|
|
191
|
+
groupIndex: result.deployContractTx.fromGroup,
|
|
192
|
+
contractId,
|
|
193
|
+
gasPrice: (0, api_1.fromApiNumber256)(result.deployContractTx.gasPrice)
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
236
197
|
const contractId = (0, utils_1.binToHex)((0, address_1.contractIdFromAddress)(result.contractAddress));
|
|
237
198
|
return {
|
|
238
199
|
...result,
|
|
@@ -242,6 +203,19 @@ class TransactionBuilder {
|
|
|
242
203
|
};
|
|
243
204
|
}
|
|
244
205
|
convertExecuteScriptTxResult(result) {
|
|
206
|
+
if ('transferTxs' in result) {
|
|
207
|
+
return {
|
|
208
|
+
transferTxs: result.transferTxs.map((r) => ({
|
|
209
|
+
...r,
|
|
210
|
+
gasPrice: (0, api_1.fromApiNumber256)(r.gasPrice)
|
|
211
|
+
})),
|
|
212
|
+
tx: {
|
|
213
|
+
...result.executeScriptTx,
|
|
214
|
+
groupIndex: result.executeScriptTx.fromGroup,
|
|
215
|
+
gasPrice: (0, api_1.fromApiNumber256)(result.executeScriptTx.gasPrice)
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
245
219
|
return {
|
|
246
220
|
...result,
|
|
247
221
|
groupIndex: result.fromGroup,
|
|
@@ -11,7 +11,7 @@ export interface Destination {
|
|
|
11
11
|
lockTime?: number;
|
|
12
12
|
message?: string;
|
|
13
13
|
}
|
|
14
|
-
export type KeyType = 'default' | 'bip340-schnorr' | '
|
|
14
|
+
export type KeyType = 'default' | 'bip340-schnorr' | 'gl-secp256k1' | 'gl-secp256r1' | 'gl-ed25519' | 'gl-webauthn';
|
|
15
15
|
export interface Account {
|
|
16
16
|
keyType: KeyType;
|
|
17
17
|
address: string;
|
|
@@ -29,6 +29,7 @@ export interface SignTransferTxParams {
|
|
|
29
29
|
utxos?: OutputRef[];
|
|
30
30
|
gasAmount?: number;
|
|
31
31
|
gasPrice?: Number256;
|
|
32
|
+
group?: number;
|
|
32
33
|
}
|
|
33
34
|
export interface SignTransferTxResult {
|
|
34
35
|
fromGroup: number;
|
|
@@ -49,6 +50,7 @@ export interface SignDeployContractTxParams {
|
|
|
49
50
|
issueTokenTo?: string;
|
|
50
51
|
gasAmount?: number;
|
|
51
52
|
gasPrice?: Number256;
|
|
53
|
+
group?: number;
|
|
52
54
|
}
|
|
53
55
|
export interface SignDeployContractTxResult {
|
|
54
56
|
groupIndex: number;
|
|
@@ -69,6 +71,7 @@ export interface SignExecuteScriptTxParams {
|
|
|
69
71
|
gasAmount?: number;
|
|
70
72
|
gasPrice?: Number256;
|
|
71
73
|
gasEstimationMultiplier?: number;
|
|
74
|
+
group?: number;
|
|
72
75
|
}
|
|
73
76
|
export interface SignExecuteScriptTxResult {
|
|
74
77
|
groupIndex: number;
|
|
@@ -79,6 +82,16 @@ export interface SignExecuteScriptTxResult {
|
|
|
79
82
|
gasPrice: Number256;
|
|
80
83
|
simulationResult: SimulationResult;
|
|
81
84
|
}
|
|
85
|
+
export interface GrouplessBuildTxResult<T extends SignExecuteScriptTxResult | SignDeployContractTxResult | SignTransferTxResult> {
|
|
86
|
+
transferTxs: Omit<SignTransferTxResult, 'signature'>[];
|
|
87
|
+
tx: Omit<T, 'signature'>;
|
|
88
|
+
}
|
|
89
|
+
export type BuildTxResult<T extends SignExecuteScriptTxResult | SignDeployContractTxResult | SignTransferTxResult> = GrouplessBuildTxResult<T> | Omit<T, 'signature'>;
|
|
90
|
+
export interface GrouplessSignTxResult<T extends SignExecuteScriptTxResult | SignDeployContractTxResult | SignTransferTxResult> {
|
|
91
|
+
transferTxs: SignTransferTxResult[];
|
|
92
|
+
tx: T;
|
|
93
|
+
}
|
|
94
|
+
export type SignTxResult<T extends SignExecuteScriptTxResult | SignDeployContractTxResult | SignTransferTxResult> = GrouplessSignTxResult<T> | T;
|
|
82
95
|
export interface SignUnsignedTxParams {
|
|
83
96
|
signerAddress: string;
|
|
84
97
|
signerKeyType?: KeyType;
|
|
@@ -113,32 +126,6 @@ export type SignExecuteScriptChainedTxResult = SignExecuteScriptTxResult & {
|
|
|
113
126
|
type: 'ExecuteScript';
|
|
114
127
|
};
|
|
115
128
|
export type SignChainedTxResult = SignTransferChainedTxResult | SignDeployContractChainedTxResult | SignExecuteScriptChainedTxResult;
|
|
116
|
-
export interface SignGrouplessTransferTxParams {
|
|
117
|
-
fromAddress: string;
|
|
118
|
-
destinations: Destination[];
|
|
119
|
-
gasPrice?: Number256;
|
|
120
|
-
targetBlockHash?: string;
|
|
121
|
-
}
|
|
122
|
-
export interface SignGrouplessDeployContractTxParams {
|
|
123
|
-
fromAddress: string;
|
|
124
|
-
bytecode: string;
|
|
125
|
-
initialAttoAlphAmount?: Number256;
|
|
126
|
-
initialTokenAmounts?: Token[];
|
|
127
|
-
issueTokenAmount?: Number256;
|
|
128
|
-
issueTokenTo?: string;
|
|
129
|
-
gasPrice?: Number256;
|
|
130
|
-
targetBlockHash?: string;
|
|
131
|
-
}
|
|
132
|
-
export interface SignGrouplessExecuteScriptTxParams {
|
|
133
|
-
fromAddress: string;
|
|
134
|
-
bytecode: string;
|
|
135
|
-
attoAlphAmount?: Number256;
|
|
136
|
-
tokens?: Token[];
|
|
137
|
-
gasPrice?: Number256;
|
|
138
|
-
targetBlockHash?: string;
|
|
139
|
-
gasEstimationMultiplier?: number;
|
|
140
|
-
}
|
|
141
|
-
export type SignGrouplessTxParams = SignGrouplessTransferTxParams | SignGrouplessDeployContractTxParams | SignGrouplessExecuteScriptTxParams;
|
|
142
129
|
export type MessageHasher = 'alephium' | 'sha256' | 'blake2b' | 'identity';
|
|
143
130
|
export interface SignMessageParams {
|
|
144
131
|
signerAddress: string;
|
package/dist/src/signer/types.js
CHANGED
package/dist/src/utils/sign.js
CHANGED
|
@@ -60,7 +60,7 @@ necc.utils.hmacSha256Sync = (key, ...messages) => {
|
|
|
60
60
|
// hash has to be 32 bytes
|
|
61
61
|
function sign(hash, privateKey, _keyType) {
|
|
62
62
|
const keyType = _keyType ?? 'default';
|
|
63
|
-
if (keyType === 'default' || keyType === '
|
|
63
|
+
if (keyType === 'default' || keyType === 'gl-secp256k1') {
|
|
64
64
|
const key = ec.keyFromPrivate(privateKey);
|
|
65
65
|
const signature = key.sign(hash);
|
|
66
66
|
return (0, utils_1.encodeSignature)(signature);
|
|
@@ -74,7 +74,7 @@ exports.sign = sign;
|
|
|
74
74
|
function verifySignature(hash, publicKey, signature, _keyType) {
|
|
75
75
|
const keyType = _keyType ?? 'default';
|
|
76
76
|
try {
|
|
77
|
-
if (keyType === 'default' || keyType === '
|
|
77
|
+
if (keyType === 'default' || keyType === 'gl-secp256k1') {
|
|
78
78
|
const key = ec.keyFromPublic(publicKey, 'hex');
|
|
79
79
|
return key.verify(hash, (0, utils_1.signatureDecode)(ec, signature));
|
|
80
80
|
}
|
package/package.json
CHANGED
package/src/address/address.ts
CHANGED
|
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License
|
|
|
16
16
|
along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { ec as EC } from 'elliptic'
|
|
19
|
+
import { ec as EC, eddsa as EdDSA } from 'elliptic'
|
|
20
20
|
import BN from 'bn.js'
|
|
21
21
|
import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
22
22
|
import blake from 'blakejs'
|
|
@@ -30,7 +30,9 @@ import djb2 from '../utils/djb2'
|
|
|
30
30
|
import { TraceableError } from '../error'
|
|
31
31
|
import { byteCodec } from '../codec/codec'
|
|
32
32
|
|
|
33
|
-
const
|
|
33
|
+
const secp256k1 = new EC('secp256k1')
|
|
34
|
+
const secp256r1 = new EC('p256')
|
|
35
|
+
const ed25519 = new EdDSA('ed25519')
|
|
34
36
|
const PublicKeyHashSize = 32
|
|
35
37
|
|
|
36
38
|
export enum AddressType {
|
|
@@ -96,10 +98,14 @@ function decodeAndValidateAddress(address: string): Uint8Array {
|
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
function isGrouplessAddressWithoutGroup(decoded: Uint8Array): boolean {
|
|
101
|
+
// An ED25519 public key is 32 bytes; other public keys are 33 bytes.
|
|
102
|
+
// Format: AddressType(1 byte) + KeyType(1 byte) + PublicKey(32/33 bytes) + Checksum(4 bytes)
|
|
99
103
|
return decoded[0] === AddressType.P2PK && (decoded.length === 38 || decoded.length === 39)
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
function isGrouplessAddressWithGroup(decoded: Uint8Array): boolean {
|
|
107
|
+
// An ED25519 public key is 32 bytes; other public keys are 33 bytes.
|
|
108
|
+
// Format: AddressType(1 byte) + KeyType(1 byte) + PublicKey(32/33 bytes) + Checksum(4 bytes) + GroupIndex(1 byte)
|
|
103
109
|
return decoded[0] === AddressType.P2PK && (decoded.length === 39 || decoded.length === 40)
|
|
104
110
|
}
|
|
105
111
|
|
|
@@ -222,29 +228,47 @@ export function groupOfPrivateKey(privateKey: string, keyType?: KeyType): number
|
|
|
222
228
|
export function publicKeyFromPrivateKey(privateKey: string, _keyType?: KeyType): string {
|
|
223
229
|
const keyType = _keyType ?? 'default'
|
|
224
230
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
231
|
+
switch (keyType) {
|
|
232
|
+
case 'default':
|
|
233
|
+
case 'gl-secp256k1':
|
|
234
|
+
return secp256k1.keyFromPrivate(privateKey).getPublic(true, 'hex')
|
|
235
|
+
case 'gl-secp256r1':
|
|
236
|
+
case 'gl-webauthn':
|
|
237
|
+
return secp256r1.keyFromPrivate(privateKey).getPublic(true, 'hex')
|
|
238
|
+
case 'gl-ed25519':
|
|
239
|
+
return ed25519.keyFromSecret(privateKey).getPublic('hex')
|
|
240
|
+
case 'bip340-schnorr':
|
|
241
|
+
return secp256k1.g.mul(new BN(privateKey, 16)).encode('hex', true).slice(2)
|
|
230
242
|
}
|
|
231
243
|
}
|
|
232
244
|
|
|
245
|
+
function p2pkAddressFromPublicKey(
|
|
246
|
+
publicKey: string,
|
|
247
|
+
keyType: 'gl-secp256k1' | 'gl-secp256r1' | 'gl-ed25519' | 'gl-webauthn'
|
|
248
|
+
): string {
|
|
249
|
+
const keyTypeByte =
|
|
250
|
+
keyType === 'gl-secp256k1' ? 0x00 : keyType === 'gl-secp256r1' ? 0x01 : keyType === 'gl-ed25519' ? 0x02 : 0x03
|
|
251
|
+
const publicKeyBytes = new Uint8Array([keyTypeByte, ...hexToBinUnsafe(publicKey)])
|
|
252
|
+
const checksum = intAs4BytesCodec.encode(djb2(publicKeyBytes))
|
|
253
|
+
const bytes = new Uint8Array([AddressType.P2PK, ...publicKeyBytes, ...checksum])
|
|
254
|
+
return bs58.encode(bytes)
|
|
255
|
+
}
|
|
256
|
+
|
|
233
257
|
export function addressFromPublicKey(publicKey: string, _keyType?: KeyType): string {
|
|
234
258
|
const keyType = _keyType ?? 'default'
|
|
235
259
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
260
|
+
switch (keyType) {
|
|
261
|
+
case 'default': {
|
|
262
|
+
const hash = blake.blake2b(hexToBinUnsafe(publicKey), undefined, 32)
|
|
263
|
+
const bytes = new Uint8Array([AddressType.P2PKH, ...hash])
|
|
264
|
+
return bs58.encode(bytes)
|
|
265
|
+
}
|
|
266
|
+
case 'bip340-schnorr': {
|
|
267
|
+
const lockupScript = hexToBinUnsafe(`0101000000000458144020${publicKey}8685`)
|
|
268
|
+
return addressFromScript(lockupScript)
|
|
269
|
+
}
|
|
270
|
+
default:
|
|
271
|
+
return p2pkAddressFromPublicKey(publicKey, keyType)
|
|
248
272
|
}
|
|
249
273
|
}
|
|
250
274
|
|
|
@@ -319,6 +343,13 @@ export function hasExplicitGroupIndex(address: string): boolean {
|
|
|
319
343
|
return address.length > 2 && address[address.length - 2] === ':'
|
|
320
344
|
}
|
|
321
345
|
|
|
346
|
+
export function addressWithoutExplicitGroupIndex(address: string): string {
|
|
347
|
+
if (hasExplicitGroupIndex(address)) {
|
|
348
|
+
return address.slice(0, address.length - 2)
|
|
349
|
+
}
|
|
350
|
+
return address
|
|
351
|
+
}
|
|
352
|
+
|
|
322
353
|
export function addressFromLockupScript(lockupScript: LockupScript): string {
|
|
323
354
|
if (lockupScript.kind === 'P2PK') {
|
|
324
355
|
const groupByte = lockupScriptCodec.encode(lockupScript).slice(-1)
|