@alephium/web3 0.22.0 → 0.23.0

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.
@@ -38,15 +38,15 @@ export declare enum StdInterfaceIds {
38
38
  NFTCollectionWithRoyalty = "000201"
39
39
  }
40
40
  export interface FungibleTokenMetaData {
41
- name: string;
42
41
  symbol: string;
42
+ name: string;
43
43
  decimals: number;
44
44
  totalSupply: Number256;
45
45
  }
46
46
  export interface NFTMetaData {
47
+ tokenUri: string;
47
48
  collectionId: string;
48
49
  nftIndex: Number256;
49
- tokenUri: string;
50
50
  }
51
51
  export interface NFTCollectionMetaData {
52
52
  collectionUri: string;
@@ -556,9 +556,9 @@ class Contract extends Artifact {
556
556
  const fields = this.stdInterfaceId === undefined
557
557
  ? this.fieldsSig
558
558
  : {
559
- names: this.fieldsSig.names.slice(-1),
560
- types: this.fieldsSig.types.slice(-1),
561
- isMutable: this.fieldsSig.isMutable.slice(-1)
559
+ names: this.fieldsSig.names.slice(0, -1),
560
+ types: this.fieldsSig.types.slice(0, -1),
561
+ isMutable: this.fieldsSig.isMutable.slice(0, -1)
562
562
  };
563
563
  return fields.names.reduce((acc, key, index) => {
564
564
  acc[`${key}`] = (0, api_1.getDefaultValue)(fields.types[`${index}`]);
@@ -0,0 +1,7 @@
1
+ import { Transaction } from '../api/api-alephium';
2
+ import { Address } from '../signer';
3
+ export declare function isExchangeAddress(address: string): boolean;
4
+ export declare function isDepositALPHTransaction(tx: Transaction, exchangeAddress: string): boolean;
5
+ export declare function isDepositTokenTransaction(tx: Transaction, exchangeAddress: string): boolean;
6
+ export declare function getDepositAddress(tx: Transaction): Address;
7
+ export declare function getAddressFromUnlockScript(unlockScript: string): Address;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /*
3
+ Copyright 2018 - 2022 The Alephium Authors
4
+ This file is part of the alephium project.
5
+
6
+ The library is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ The library is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.getAddressFromUnlockScript = exports.getDepositAddress = exports.isDepositTokenTransaction = exports.isDepositALPHTransaction = exports.isExchangeAddress = void 0;
21
+ const __1 = require("..");
22
+ function isExchangeAddress(address) {
23
+ const decoded = __1.bs58.decode(address);
24
+ if (decoded.length === 0)
25
+ throw new Error('Address is empty');
26
+ const addressType = decoded[0];
27
+ return (addressType === __1.AddressType.P2PKH || addressType === __1.AddressType.P2SH) && decoded.length === 33;
28
+ }
29
+ exports.isExchangeAddress = isExchangeAddress;
30
+ function isDepositALPHTransaction(tx, exchangeAddress) {
31
+ return isDepositTransaction(tx, exchangeAddress) && checkALPHOutput(tx);
32
+ }
33
+ exports.isDepositALPHTransaction = isDepositALPHTransaction;
34
+ function isDepositTokenTransaction(tx, exchangeAddress) {
35
+ return isDepositTransaction(tx, exchangeAddress) && checkTokenOutput(tx, exchangeAddress);
36
+ }
37
+ exports.isDepositTokenTransaction = isDepositTokenTransaction;
38
+ // we assume that the tx is deposit transaction
39
+ function getDepositAddress(tx) {
40
+ return getAddressFromUnlockScript(tx.unsigned.inputs[0].unlockScript);
41
+ }
42
+ exports.getDepositAddress = getDepositAddress;
43
+ var UnlockScriptType;
44
+ (function (UnlockScriptType) {
45
+ UnlockScriptType[UnlockScriptType["P2PKH"] = 0] = "P2PKH";
46
+ UnlockScriptType[UnlockScriptType["P2MPKH"] = 1] = "P2MPKH";
47
+ UnlockScriptType[UnlockScriptType["P2SH"] = 2] = "P2SH";
48
+ })(UnlockScriptType || (UnlockScriptType = {}));
49
+ function getAddressFromUnlockScript(unlockScript) {
50
+ const decoded = (0, __1.hexToBinUnsafe)(unlockScript);
51
+ if (decoded.length === 0)
52
+ throw new Error('UnlockScript is empty');
53
+ const unlockScriptType = decoded[0];
54
+ const unlockScriptBody = decoded.slice(1);
55
+ if (unlockScriptType === UnlockScriptType.P2PKH) {
56
+ return (0, __1.addressFromPublicKey)((0, __1.binToHex)(unlockScriptBody));
57
+ }
58
+ else if (unlockScriptType === UnlockScriptType.P2MPKH) {
59
+ throw new Error('Naive multi-sig address is not supported for exchanges as it will be replaced by P2SH');
60
+ }
61
+ else if (unlockScriptType === UnlockScriptType.P2SH) {
62
+ // FIXEME: for now we assume that the params is empty, so we need to
63
+ // remove the last byte from the `unlockScriptBody`, we can decode
64
+ // the unlock script once the codec PR is merged
65
+ const script = unlockScriptBody.slice(0, -1);
66
+ return (0, __1.addressFromScript)(script);
67
+ }
68
+ else {
69
+ throw new Error('Invalid unlock script type');
70
+ }
71
+ }
72
+ exports.getAddressFromUnlockScript = getAddressFromUnlockScript;
73
+ function getFromAddress(tx) {
74
+ try {
75
+ const inputAddresses = tx.unsigned.inputs.map((i) => getAddressFromUnlockScript(i.unlockScript));
76
+ // we have checked that the inputs is not empty
77
+ const from = inputAddresses[0];
78
+ return inputAddresses.slice(1).every((addr) => addr === from) ? from : undefined;
79
+ }
80
+ catch (_) {
81
+ return undefined;
82
+ }
83
+ }
84
+ function checkOutputAddress(tx, from, to) {
85
+ let fromCount = 0;
86
+ let toCount = 0;
87
+ tx.unsigned.fixedOutputs.forEach((o) => {
88
+ if (o.address === from) {
89
+ fromCount += 1;
90
+ }
91
+ else if (o.address === to) {
92
+ toCount += 1;
93
+ }
94
+ });
95
+ const outputCount = tx.unsigned.fixedOutputs.length;
96
+ return toCount === 1 && fromCount === outputCount - 1;
97
+ }
98
+ function checkALPHOutput(tx) {
99
+ const outputs = tx.unsigned.fixedOutputs;
100
+ return outputs.every((o) => o.tokens.length === 0);
101
+ }
102
+ function checkTokenOutput(tx, to) {
103
+ // we have checked the output address
104
+ const output = tx.unsigned.fixedOutputs.find((o) => o.address === to);
105
+ return output.attoAlphAmount === __1.DUST_AMOUNT.toString() && output.tokens.length === 1;
106
+ }
107
+ function isDepositTransaction(tx, exchangeAddress) {
108
+ if (tx.contractInputs.length !== 0 ||
109
+ tx.generatedOutputs.length !== 0 ||
110
+ tx.unsigned.inputs.length === 0 ||
111
+ tx.unsigned.scriptOpt !== undefined) {
112
+ return false;
113
+ }
114
+ const from = getFromAddress(tx);
115
+ if (from === undefined) {
116
+ return false;
117
+ }
118
+ return checkOutputAddress(tx, from, exchangeAddress);
119
+ }
@@ -6,3 +6,4 @@ export * from './utils';
6
6
  export * from './subscription';
7
7
  export * from './sign';
8
8
  export * from './number';
9
+ export { isExchangeAddress, isDepositALPHTransaction, isDepositTokenTransaction, getDepositAddress } from './exchange';
@@ -31,6 +31,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
31
31
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
32
32
  };
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
+ exports.getDepositAddress = exports.isDepositTokenTransaction = exports.isDepositALPHTransaction = exports.isExchangeAddress = void 0;
34
35
  __exportStar(require("./webcrypto"), exports);
35
36
  __exportStar(require("./address"), exports);
36
37
  __exportStar(require("./bs58"), exports);
@@ -39,3 +40,8 @@ __exportStar(require("./utils"), exports);
39
40
  __exportStar(require("./subscription"), exports);
40
41
  __exportStar(require("./sign"), exports);
41
42
  __exportStar(require("./number"), exports);
43
+ var exchange_1 = require("./exchange");
44
+ Object.defineProperty(exports, "isExchangeAddress", { enumerable: true, get: function () { return exchange_1.isExchangeAddress; } });
45
+ Object.defineProperty(exports, "isDepositALPHTransaction", { enumerable: true, get: function () { return exchange_1.isDepositALPHTransaction; } });
46
+ Object.defineProperty(exports, "isDepositTokenTransaction", { enumerable: true, get: function () { return exchange_1.isDepositTokenTransaction; } });
47
+ Object.defineProperty(exports, "getDepositAddress", { enumerable: true, get: function () { return exchange_1.getDepositAddress; } });
@@ -13,6 +13,12 @@ export declare function signatureDecode(ec: EC, signature: string): SignatureInp
13
13
  export declare function xorByte(intValue: number): number;
14
14
  export declare function isHexString(input: string): boolean;
15
15
  export declare function toNonNegativeBigInt(input: string): bigint | undefined;
16
+ export declare enum AddressType {
17
+ P2PKH = 0,
18
+ P2MPKH = 1,
19
+ P2SH = 2,
20
+ P2C = 3
21
+ }
16
22
  export declare function groupOfAddress(address: string): number;
17
23
  export declare function contractIdFromAddress(address: string): Uint8Array;
18
24
  export declare function tokenIdFromAddress(address: string): Uint8Array;
@@ -21,6 +27,7 @@ export declare function binToHex(bin: Uint8Array): string;
21
27
  export declare function groupOfPrivateKey(privateKey: string, keyType?: KeyType): number;
22
28
  export declare function publicKeyFromPrivateKey(privateKey: string, _keyType?: KeyType): string;
23
29
  export declare function addressFromPublicKey(publicKey: string, _keyType?: KeyType): string;
30
+ export declare function addressFromScript(script: Uint8Array): string;
24
31
  export declare function addressFromContractId(contractId: string): string;
25
32
  export declare function addressFromTokenId(tokenId: string): string;
26
33
  export declare function contractIdFromTx(txId: string, outputIndex: number): string;
@@ -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.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.toNonNegativeBigInt = exports.isHexString = exports.xorByte = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
23
+ exports.assertType = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromScript = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.AddressType = exports.toNonNegativeBigInt = exports.isHexString = exports.xorByte = 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 blakejs_1 = __importDefault(require("blakejs"));
@@ -88,7 +88,7 @@ var AddressType;
88
88
  AddressType[AddressType["P2MPKH"] = 1] = "P2MPKH";
89
89
  AddressType[AddressType["P2SH"] = 2] = "P2SH";
90
90
  AddressType[AddressType["P2C"] = 3] = "P2C";
91
- })(AddressType || (AddressType = {}));
91
+ })(AddressType = exports.AddressType || (exports.AddressType = {}));
92
92
  function groupOfAddress(address) {
93
93
  const decoded = bs58_1.default.decode(address);
94
94
  if (decoded.length == 0)
@@ -189,12 +189,16 @@ function addressFromPublicKey(publicKey, _keyType) {
189
189
  }
190
190
  else {
191
191
  const lockupScript = buffer_1.Buffer.from(`0101000000000458144020${publicKey}8685`, 'hex');
192
- const lockupScriptHash = blakejs_1.default.blake2b(lockupScript, undefined, 32);
193
- const addressType = buffer_1.Buffer.from([AddressType.P2SH]);
194
- return bs58_1.default.encode(buffer_1.Buffer.concat([addressType, lockupScriptHash]));
192
+ return addressFromScript(lockupScript);
195
193
  }
196
194
  }
197
195
  exports.addressFromPublicKey = addressFromPublicKey;
196
+ function addressFromScript(script) {
197
+ const scriptHash = blakejs_1.default.blake2b(script, undefined, 32);
198
+ const addressType = buffer_1.Buffer.from([AddressType.P2SH]);
199
+ return bs58_1.default.encode(buffer_1.Buffer.concat([addressType, scriptHash]));
200
+ }
201
+ exports.addressFromScript = addressFromScript;
198
202
  function addressFromContractId(contractId) {
199
203
  const addressType = buffer_1.Buffer.from([AddressType.P2C]);
200
204
  const hash = buffer_1.Buffer.from(hexToBinUnsafe(contractId));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "A JS/TS library to interact with the Alephium platform",
5
5
  "license": "GPL",
6
6
  "main": "dist/src/index.js",
@@ -82,7 +82,7 @@
82
82
  "webpack-cli": "^4.10.0"
83
83
  },
84
84
  "engines": {
85
- "node": ">=16.0.0",
85
+ "node": ">=14.0.0",
86
86
  "npm": ">=7.0.0"
87
87
  },
88
88
  "scripts": {
package/src/api/types.ts CHANGED
@@ -291,16 +291,16 @@ export enum StdInterfaceIds {
291
291
  }
292
292
 
293
293
  export interface FungibleTokenMetaData {
294
- name: string
295
294
  symbol: string
295
+ name: string
296
296
  decimals: number
297
297
  totalSupply: Number256
298
298
  }
299
299
 
300
300
  export interface NFTMetaData {
301
+ tokenUri: string
301
302
  collectionId: string
302
303
  nftIndex: Number256
303
- tokenUri: string
304
304
  }
305
305
 
306
306
  export interface NFTCollectionMetaData {
@@ -850,9 +850,9 @@ export class Contract extends Artifact {
850
850
  this.stdInterfaceId === undefined
851
851
  ? this.fieldsSig
852
852
  : {
853
- names: this.fieldsSig.names.slice(-1),
854
- types: this.fieldsSig.types.slice(-1),
855
- isMutable: this.fieldsSig.isMutable.slice(-1)
853
+ names: this.fieldsSig.names.slice(0, -1),
854
+ types: this.fieldsSig.types.slice(0, -1),
855
+ isMutable: this.fieldsSig.isMutable.slice(0, -1)
856
856
  }
857
857
  return fields.names.reduce((acc, key, index) => {
858
858
  acc[`${key}`] = getDefaultValue(fields.types[`${index}`])
@@ -0,0 +1,120 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import { AddressType, DUST_AMOUNT, addressFromPublicKey, addressFromScript, binToHex, bs58, hexToBinUnsafe } from '..'
20
+ import { Transaction } from '../api/api-alephium'
21
+ import { Address } from '../signer'
22
+
23
+ export function isExchangeAddress(address: string): boolean {
24
+ const decoded = bs58.decode(address)
25
+ if (decoded.length === 0) throw new Error('Address is empty')
26
+ const addressType = decoded[0]
27
+ return (addressType === AddressType.P2PKH || addressType === AddressType.P2SH) && decoded.length === 33
28
+ }
29
+
30
+ export function isDepositALPHTransaction(tx: Transaction, exchangeAddress: string): boolean {
31
+ return isDepositTransaction(tx, exchangeAddress) && checkALPHOutput(tx)
32
+ }
33
+
34
+ export function isDepositTokenTransaction(tx: Transaction, exchangeAddress: string): boolean {
35
+ return isDepositTransaction(tx, exchangeAddress) && checkTokenOutput(tx, exchangeAddress)
36
+ }
37
+
38
+ // we assume that the tx is deposit transaction
39
+ export function getDepositAddress(tx: Transaction): Address {
40
+ return getAddressFromUnlockScript(tx.unsigned.inputs[0].unlockScript)
41
+ }
42
+
43
+ enum UnlockScriptType {
44
+ P2PKH = 0x00,
45
+ P2MPKH = 0x01,
46
+ P2SH = 0x02
47
+ }
48
+
49
+ export function getAddressFromUnlockScript(unlockScript: string): Address {
50
+ const decoded = hexToBinUnsafe(unlockScript)
51
+ if (decoded.length === 0) throw new Error('UnlockScript is empty')
52
+ const unlockScriptType = decoded[0]
53
+ const unlockScriptBody = decoded.slice(1)
54
+
55
+ if (unlockScriptType === UnlockScriptType.P2PKH) {
56
+ return addressFromPublicKey(binToHex(unlockScriptBody))
57
+ } else if (unlockScriptType === UnlockScriptType.P2MPKH) {
58
+ throw new Error('Naive multi-sig address is not supported for exchanges as it will be replaced by P2SH')
59
+ } else if (unlockScriptType === UnlockScriptType.P2SH) {
60
+ // FIXEME: for now we assume that the params is empty, so we need to
61
+ // remove the last byte from the `unlockScriptBody`, we can decode
62
+ // the unlock script once the codec PR is merged
63
+ const script = unlockScriptBody.slice(0, -1)
64
+ return addressFromScript(script)
65
+ } else {
66
+ throw new Error('Invalid unlock script type')
67
+ }
68
+ }
69
+
70
+ function getFromAddress(tx: Transaction): Address | undefined {
71
+ try {
72
+ const inputAddresses = tx.unsigned.inputs.map((i) => getAddressFromUnlockScript(i.unlockScript))
73
+ // we have checked that the inputs is not empty
74
+ const from = inputAddresses[0]
75
+ return inputAddresses.slice(1).every((addr) => addr === from) ? from : undefined
76
+ } catch (_) {
77
+ return undefined
78
+ }
79
+ }
80
+
81
+ function checkOutputAddress(tx: Transaction, from: Address, to: Address): boolean {
82
+ let fromCount = 0
83
+ let toCount = 0
84
+ tx.unsigned.fixedOutputs.forEach((o) => {
85
+ if (o.address === from) {
86
+ fromCount += 1
87
+ } else if (o.address === to) {
88
+ toCount += 1
89
+ }
90
+ })
91
+ const outputCount = tx.unsigned.fixedOutputs.length
92
+ return toCount === 1 && fromCount === outputCount - 1
93
+ }
94
+
95
+ function checkALPHOutput(tx: Transaction): boolean {
96
+ const outputs = tx.unsigned.fixedOutputs
97
+ return outputs.every((o) => o.tokens.length === 0)
98
+ }
99
+
100
+ function checkTokenOutput(tx: Transaction, to: Address): boolean {
101
+ // we have checked the output address
102
+ const output = tx.unsigned.fixedOutputs.find((o) => o.address === to)!
103
+ return output.attoAlphAmount === DUST_AMOUNT.toString() && output.tokens.length === 1
104
+ }
105
+
106
+ function isDepositTransaction(tx: Transaction, exchangeAddress: string): boolean {
107
+ if (
108
+ tx.contractInputs.length !== 0 ||
109
+ tx.generatedOutputs.length !== 0 ||
110
+ tx.unsigned.inputs.length === 0 ||
111
+ tx.unsigned.scriptOpt !== undefined
112
+ ) {
113
+ return false
114
+ }
115
+ const from = getFromAddress(tx)
116
+ if (from === undefined) {
117
+ return false
118
+ }
119
+ return checkOutputAddress(tx, from, exchangeAddress)
120
+ }
@@ -24,3 +24,4 @@ export * from './utils'
24
24
  export * from './subscription'
25
25
  export * from './sign'
26
26
  export * from './number'
27
+ export { isExchangeAddress, isDepositALPHTransaction, isDepositTokenTransaction, getDepositAddress } from './exchange'
@@ -84,7 +84,7 @@ export function toNonNegativeBigInt(input: string): bigint | undefined {
84
84
  }
85
85
  }
86
86
 
87
- enum AddressType {
87
+ export enum AddressType {
88
88
  P2PKH = 0x00,
89
89
  P2MPKH = 0x01,
90
90
  P2SH = 0x02,
@@ -196,12 +196,16 @@ export function addressFromPublicKey(publicKey: string, _keyType?: KeyType): str
196
196
  return bs58.encode(bytes)
197
197
  } else {
198
198
  const lockupScript = Buffer.from(`0101000000000458144020${publicKey}8685`, 'hex')
199
- const lockupScriptHash = blake.blake2b(lockupScript, undefined, 32)
200
- const addressType = Buffer.from([AddressType.P2SH])
201
- return bs58.encode(Buffer.concat([addressType, lockupScriptHash]))
199
+ return addressFromScript(lockupScript)
202
200
  }
203
201
  }
204
202
 
203
+ export function addressFromScript(script: Uint8Array): string {
204
+ const scriptHash = blake.blake2b(script, undefined, 32)
205
+ const addressType = Buffer.from([AddressType.P2SH])
206
+ return bs58.encode(Buffer.concat([addressType, scriptHash]))
207
+ }
208
+
205
209
  export function addressFromContractId(contractId: string): string {
206
210
  const addressType = Buffer.from([AddressType.P2C])
207
211
  const hash = Buffer.from(hexToBinUnsafe(contractId))