@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.
@@ -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' | 'groupless';
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;
@@ -28,6 +28,3 @@ utils_1.assertType;
28
28
  (0, utils_1.assertType)();
29
29
  utils_1.assertType;
30
30
  (0, utils_1.assertType)();
31
- (0, utils_1.assertType)();
32
- (0, utils_1.assertType)();
33
- (0, utils_1.assertType)();
@@ -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 === 'groupless') {
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 === 'groupless') {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "1.12.0-beta.0",
3
+ "version": "1.12.0-danube.1",
4
4
  "description": "A JS/TS library to interact with the Alephium platform",
5
5
  "license": "GPL",
6
6
  "main": "dist/src/index.js",
@@ -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 ec = new EC('secp256k1')
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
- if (keyType === 'default' || keyType === 'groupless') {
226
- const key = ec.keyFromPrivate(privateKey)
227
- return key.getPublic(true, 'hex')
228
- } else {
229
- return ec.g.mul(new BN(privateKey, 16)).encode('hex', true).slice(2)
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
- if (keyType === 'default') {
237
- const hash = blake.blake2b(hexToBinUnsafe(publicKey), undefined, 32)
238
- const bytes = new Uint8Array([AddressType.P2PKH, ...hash])
239
- return bs58.encode(bytes)
240
- } else if (keyType === 'groupless') {
241
- const publicKeyBytes = new Uint8Array([0x00, ...hexToBinUnsafe(publicKey)])
242
- const hashBytes = intAs4BytesCodec.encode(djb2(publicKeyBytes))
243
- const bytes = new Uint8Array([0x04, ...publicKeyBytes, ...hashBytes])
244
- return bs58.encode(bytes)
245
- } else {
246
- const lockupScript = hexToBinUnsafe(`0101000000000458144020${publicKey}8685`)
247
- return addressFromScript(lockupScript)
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)