@alephium/web3 0.44.0 → 1.0.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.
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/address/address.js +7 -2
- package/dist/src/api/api-alephium.d.ts +154 -1
- package/dist/src/api/api-alephium.js +15 -1
- package/dist/src/api/api-explorer.d.ts +51 -0
- package/dist/src/api/api-explorer.js +26 -0
- package/dist/src/block/block.d.ts +12 -13
- package/dist/src/block/block.js +94 -53
- package/package.json +11 -5
- package/src/address/address.ts +6 -2
- package/src/api/api-alephium.ts +162 -1
- package/src/api/api-explorer.ts +74 -0
- package/src/block/block.ts +108 -65
|
@@ -151,7 +151,7 @@ class HttpClient {
|
|
|
151
151
|
exports.HttpClient = HttpClient;
|
|
152
152
|
/**
|
|
153
153
|
* @title Alephium API
|
|
154
|
-
* @version
|
|
154
|
+
* @version 3.1.0
|
|
155
155
|
* @baseUrl ../
|
|
156
156
|
*/
|
|
157
157
|
class Api extends HttpClient {
|
|
@@ -675,6 +675,20 @@ class Api extends HttpClient {
|
|
|
675
675
|
format: 'json',
|
|
676
676
|
...params
|
|
677
677
|
}).then(utils_1.convertHttpResponse),
|
|
678
|
+
/**
|
|
679
|
+
* No description
|
|
680
|
+
*
|
|
681
|
+
* @tags Blockflow
|
|
682
|
+
* @name GetBlockflowMainChainBlockByGhostUncleGhostUncleHash
|
|
683
|
+
* @summary Get a mainchain block by ghost uncle hash
|
|
684
|
+
* @request GET:/blockflow/main-chain-block-by-ghost-uncle/{ghost_uncle_hash}
|
|
685
|
+
*/
|
|
686
|
+
getBlockflowMainChainBlockByGhostUncleGhostUncleHash: (ghostUncleHash, params = {}) => this.request({
|
|
687
|
+
path: `/blockflow/main-chain-block-by-ghost-uncle/${ghostUncleHash}`,
|
|
688
|
+
method: 'GET',
|
|
689
|
+
format: 'json',
|
|
690
|
+
...params
|
|
691
|
+
}).then(utils_1.convertHttpResponse),
|
|
678
692
|
/**
|
|
679
693
|
* No description
|
|
680
694
|
*
|
|
@@ -78,6 +78,21 @@ export interface BlockEntryLite {
|
|
|
78
78
|
/** @format bigint */
|
|
79
79
|
hashRate: string;
|
|
80
80
|
}
|
|
81
|
+
export interface ContractLiveness {
|
|
82
|
+
/** @format address */
|
|
83
|
+
parent?: string;
|
|
84
|
+
creation: ContractLivenessLocation;
|
|
85
|
+
destruction?: ContractLivenessLocation;
|
|
86
|
+
interfaceId?: StdInterfaceId;
|
|
87
|
+
}
|
|
88
|
+
export interface ContractLivenessLocation {
|
|
89
|
+
/** @format block-hash */
|
|
90
|
+
blockHash: string;
|
|
91
|
+
/** @format 32-byte-hash */
|
|
92
|
+
txHash: string;
|
|
93
|
+
/** @format int64 */
|
|
94
|
+
timestamp: number;
|
|
95
|
+
}
|
|
81
96
|
export interface ContractOutput {
|
|
82
97
|
/** @format int32 */
|
|
83
98
|
hint: number;
|
|
@@ -117,6 +132,9 @@ export interface ExplorerInfo {
|
|
|
117
132
|
/** @format int64 */
|
|
118
133
|
lastFinalizedInputTime: number;
|
|
119
134
|
}
|
|
135
|
+
export interface FungibleToken {
|
|
136
|
+
type: string;
|
|
137
|
+
}
|
|
120
138
|
export interface FungibleTokenMetadata {
|
|
121
139
|
/** @format 32-byte-hash */
|
|
122
140
|
id: string;
|
|
@@ -176,11 +194,20 @@ export interface MempoolTransaction {
|
|
|
176
194
|
/** @format int64 */
|
|
177
195
|
lastSeen: number;
|
|
178
196
|
}
|
|
197
|
+
export interface NFT {
|
|
198
|
+
type: string;
|
|
199
|
+
}
|
|
200
|
+
export interface NFTCollection {
|
|
201
|
+
type: string;
|
|
202
|
+
}
|
|
179
203
|
export interface NFTCollectionMetadata {
|
|
180
204
|
/** @format address */
|
|
181
205
|
address: string;
|
|
182
206
|
collectionUri: string;
|
|
183
207
|
}
|
|
208
|
+
export interface NFTCollectionWithRoyalty {
|
|
209
|
+
type: string;
|
|
210
|
+
}
|
|
184
211
|
export interface NFTMetadata {
|
|
185
212
|
/** @format 32-byte-hash */
|
|
186
213
|
id: string;
|
|
@@ -190,6 +217,9 @@ export interface NFTMetadata {
|
|
|
190
217
|
/** @format uint256 */
|
|
191
218
|
nftIndex: string;
|
|
192
219
|
}
|
|
220
|
+
export interface NonStandard {
|
|
221
|
+
type: string;
|
|
222
|
+
}
|
|
193
223
|
export interface NotFound {
|
|
194
224
|
detail: string;
|
|
195
225
|
resource: string;
|
|
@@ -254,6 +284,7 @@ export interface PerChainTimedCount {
|
|
|
254
284
|
export interface ServiceUnavailable {
|
|
255
285
|
detail: string;
|
|
256
286
|
}
|
|
287
|
+
export type StdInterfaceId = FungibleToken | NFT | NFTCollection | NFTCollectionWithRoyalty | NonStandard | Unknown;
|
|
257
288
|
export interface SubContracts {
|
|
258
289
|
subContracts?: string[];
|
|
259
290
|
}
|
|
@@ -324,6 +355,10 @@ export type TransactionLike = AcceptedTransaction | PendingTransaction;
|
|
|
324
355
|
export interface Unauthorized {
|
|
325
356
|
detail: string;
|
|
326
357
|
}
|
|
358
|
+
export interface Unknown {
|
|
359
|
+
id: string;
|
|
360
|
+
type: string;
|
|
361
|
+
}
|
|
327
362
|
export type Val = ValAddress | ValArray | ValBool | ValByteVec | ValI256 | ValU256;
|
|
328
363
|
export interface ValAddress {
|
|
329
364
|
/** @format address */
|
|
@@ -633,6 +668,14 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
|
|
|
633
668
|
* @request GET:/addresses/{address}/tokens/{token_id}/balance
|
|
634
669
|
*/
|
|
635
670
|
getAddressesAddressTokensTokenIdBalance: (address: string, tokenId: string, params?: RequestParams) => Promise<AddressTokenBalance>;
|
|
671
|
+
/**
|
|
672
|
+
* @description Get public key of p2pkh addresses, the address needs to have at least one input.
|
|
673
|
+
*
|
|
674
|
+
* @tags Addresses
|
|
675
|
+
* @name GetAddressesAddressPublicKey
|
|
676
|
+
* @request GET:/addresses/{address}/public-key
|
|
677
|
+
*/
|
|
678
|
+
getAddressesAddressPublicKey: (address: string, params?: RequestParams) => Promise<string>;
|
|
636
679
|
/**
|
|
637
680
|
* @description Get address tokens with balance
|
|
638
681
|
*
|
|
@@ -1037,6 +1080,14 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
|
|
|
1037
1080
|
}, params?: RequestParams) => Promise<Event[]>;
|
|
1038
1081
|
};
|
|
1039
1082
|
contracts: {
|
|
1083
|
+
/**
|
|
1084
|
+
* @description Get contract liveness
|
|
1085
|
+
*
|
|
1086
|
+
* @tags Contracts
|
|
1087
|
+
* @name GetContractsContractAddressCurrentLiveness
|
|
1088
|
+
* @request GET:/contracts/{contract_address}/current-liveness
|
|
1089
|
+
*/
|
|
1090
|
+
getContractsContractAddressCurrentLiveness: (contractAddress: string, params?: RequestParams) => Promise<ContractLiveness>;
|
|
1040
1091
|
/**
|
|
1041
1092
|
* @description Get contract parent address if exist
|
|
1042
1093
|
*
|
|
@@ -377,6 +377,19 @@ class Api extends HttpClient {
|
|
|
377
377
|
format: 'json',
|
|
378
378
|
...params
|
|
379
379
|
}).then(utils_1.convertHttpResponse),
|
|
380
|
+
/**
|
|
381
|
+
* @description Get public key of p2pkh addresses, the address needs to have at least one input.
|
|
382
|
+
*
|
|
383
|
+
* @tags Addresses
|
|
384
|
+
* @name GetAddressesAddressPublicKey
|
|
385
|
+
* @request GET:/addresses/{address}/public-key
|
|
386
|
+
*/
|
|
387
|
+
getAddressesAddressPublicKey: (address, params = {}) => this.request({
|
|
388
|
+
path: `/addresses/${address}/public-key`,
|
|
389
|
+
method: 'GET',
|
|
390
|
+
format: 'json',
|
|
391
|
+
...params
|
|
392
|
+
}).then(utils_1.convertHttpResponse),
|
|
380
393
|
/**
|
|
381
394
|
* @description Get address tokens with balance
|
|
382
395
|
*
|
|
@@ -781,6 +794,19 @@ class Api extends HttpClient {
|
|
|
781
794
|
}).then(utils_1.convertHttpResponse)
|
|
782
795
|
};
|
|
783
796
|
this.contracts = {
|
|
797
|
+
/**
|
|
798
|
+
* @description Get contract liveness
|
|
799
|
+
*
|
|
800
|
+
* @tags Contracts
|
|
801
|
+
* @name GetContractsContractAddressCurrentLiveness
|
|
802
|
+
* @request GET:/contracts/{contract_address}/current-liveness
|
|
803
|
+
*/
|
|
804
|
+
getContractsContractAddressCurrentLiveness: (contractAddress, params = {}) => this.request({
|
|
805
|
+
path: `/contracts/${contractAddress}/current-liveness`,
|
|
806
|
+
method: 'GET',
|
|
807
|
+
format: 'json',
|
|
808
|
+
...params
|
|
809
|
+
}).then(utils_1.convertHttpResponse),
|
|
784
810
|
/**
|
|
785
811
|
* @description Get contract parent address if exist
|
|
786
812
|
*
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import { Subscription, SubscribeOptions } from '../utils/subscription';
|
|
2
2
|
import * as node from '../api/api-alephium';
|
|
3
3
|
import { NodeProvider } from '../api';
|
|
4
|
-
export type ReorgCallback = (orphanBlocks: node.BlockEntry[], newBlocks: node.BlockEntry[]) => Promise<void> | void;
|
|
5
|
-
export interface BlockSubscribeOptions extends SubscribeOptions<node.BlockEntry> {
|
|
4
|
+
export type ReorgCallback = (fromGroup: number, toGroup: number, orphanBlocks: node.BlockEntry[], newBlocks: node.BlockEntry[]) => Promise<void> | void;
|
|
5
|
+
export interface BlockSubscribeOptions extends SubscribeOptions<node.BlockEntry[]> {
|
|
6
6
|
reorgCallback?: ReorgCallback;
|
|
7
7
|
}
|
|
8
|
-
export declare abstract class BlockSubscriptionBase extends Subscription<node.BlockEntry> {
|
|
8
|
+
export declare abstract class BlockSubscriptionBase extends Subscription<node.BlockEntry[]> {
|
|
9
9
|
abstract readonly reorgCallback?: ReorgCallback;
|
|
10
|
-
abstract
|
|
11
|
-
abstract readonly toGroup: number;
|
|
12
|
-
abstract getHashesAtHeight(height: number): Promise<string[]>;
|
|
10
|
+
abstract getHashesAtHeight(fromGroup: number, toGroup: number, height: number): Promise<string[]>;
|
|
13
11
|
abstract getBlockByHash(hash: string): Promise<node.BlockEntry>;
|
|
14
12
|
protected getParentHash(block: node.BlockEntry): string;
|
|
15
|
-
protected handleReorg(
|
|
13
|
+
protected handleReorg(fromGroup: number, toGroup: number, orphanBlockHash: string, newBlockHash: string): Promise<void>;
|
|
16
14
|
}
|
|
17
15
|
export declare class BlockSubscription extends BlockSubscriptionBase {
|
|
18
16
|
readonly nodeProvider: NodeProvider;
|
|
19
|
-
readonly fromGroup: number;
|
|
20
|
-
readonly toGroup: number;
|
|
21
17
|
readonly reorgCallback?: ReorgCallback;
|
|
22
|
-
private
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
private fromTimeStamp;
|
|
19
|
+
private parents;
|
|
20
|
+
private cache;
|
|
21
|
+
constructor(options: BlockSubscribeOptions, fromTimeStamp: number, nodeProvider?: NodeProvider | undefined);
|
|
22
|
+
getHashesAtHeight(fromGroup: number, toGroup: number, height: number): Promise<string[]>;
|
|
26
23
|
getBlockByHash(hash: string): Promise<node.BlockEntry>;
|
|
24
|
+
private getMissingBlocksAndHandleReorg;
|
|
25
|
+
private handleBlocks;
|
|
27
26
|
polling(): Promise<void>;
|
|
28
27
|
}
|
package/dist/src/block/block.js
CHANGED
|
@@ -43,88 +43,129 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
43
43
|
exports.BlockSubscription = exports.BlockSubscriptionBase = void 0;
|
|
44
44
|
const subscription_1 = require("../utils/subscription");
|
|
45
45
|
const web3 = __importStar(require("../global"));
|
|
46
|
+
const constants_1 = require("../constants");
|
|
47
|
+
const DEFAULT_INTERVAL = 60 * 1000; // 60 seconds
|
|
48
|
+
const EXPIRE_DURATION = 20 * 1000; // 20 seconds
|
|
46
49
|
class BlockSubscriptionBase extends subscription_1.Subscription {
|
|
47
50
|
getParentHash(block) {
|
|
48
|
-
const index = Math.floor(block.deps.length / 2) +
|
|
51
|
+
const index = Math.floor(block.deps.length / 2) + block.chainTo;
|
|
49
52
|
return block.deps[index];
|
|
50
53
|
}
|
|
51
|
-
async handleReorg(
|
|
52
|
-
console.info(`reorg occur, hash: ${
|
|
54
|
+
async handleReorg(fromGroup, toGroup, orphanBlockHash, newBlockHash) {
|
|
55
|
+
console.info(`reorg occur in chain ${fromGroup} -> ${toGroup}, orphan hash: ${orphanBlockHash}, new hash: ${newBlockHash}`);
|
|
53
56
|
if (this.reorgCallback === undefined)
|
|
54
57
|
return;
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
let
|
|
58
|
-
let fromHeight = blockHeight;
|
|
58
|
+
const orphanBlocks = [];
|
|
59
|
+
let fromHash = orphanBlockHash;
|
|
60
|
+
let canonicalHash = undefined;
|
|
59
61
|
while (true) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
fromHash = this.getParentHash(block);
|
|
67
|
-
fromHeight -= 1;
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
62
|
+
const orphanBlock = await this.getBlockByHash(fromHash);
|
|
63
|
+
orphanBlocks.push(orphanBlock);
|
|
64
|
+
const hashes = await this.getHashesAtHeight(fromGroup, toGroup, orphanBlock.height - 1);
|
|
65
|
+
const parentHash = this.getParentHash(orphanBlock);
|
|
66
|
+
if (hashes[0] === parentHash) {
|
|
67
|
+
canonicalHash = hashes[0];
|
|
70
68
|
break;
|
|
71
69
|
}
|
|
72
|
-
|
|
73
|
-
const orphanBlocks = [];
|
|
74
|
-
for (const hash of orphans.reverse()) {
|
|
75
|
-
const block = await this.getBlockByHash(hash);
|
|
76
|
-
orphanBlocks.push(block);
|
|
70
|
+
fromHash = parentHash;
|
|
77
71
|
}
|
|
78
72
|
const newBlocks = [];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
fromHash = newBlockHash;
|
|
74
|
+
while (fromHash !== canonicalHash) {
|
|
75
|
+
const newBlock = await this.getBlockByHash(fromHash);
|
|
76
|
+
newBlocks.push(newBlock);
|
|
77
|
+
fromHash = this.getParentHash(newBlock);
|
|
82
78
|
}
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
const orphans = orphanBlocks.reverse();
|
|
80
|
+
const news = newBlocks.reverse();
|
|
81
|
+
console.info(`orphan hashes: ${orphans.map((b) => b.hash)}, new hashes: ${news.map((b) => b.hash)}`);
|
|
82
|
+
await this.reorgCallback(fromGroup, toGroup, orphans, news);
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
exports.BlockSubscriptionBase = BlockSubscriptionBase;
|
|
88
86
|
class BlockSubscription extends BlockSubscriptionBase {
|
|
89
|
-
constructor(options,
|
|
87
|
+
constructor(options, fromTimeStamp, nodeProvider = undefined) {
|
|
90
88
|
super(options);
|
|
91
89
|
this.nodeProvider = nodeProvider ?? web3.getCurrentNodeProvider();
|
|
92
|
-
this.fromGroup = fromGroup;
|
|
93
|
-
this.toGroup = toGroup;
|
|
94
90
|
this.reorgCallback = options.reorgCallback;
|
|
95
|
-
this.
|
|
96
|
-
this.
|
|
91
|
+
this.fromTimeStamp = fromTimeStamp;
|
|
92
|
+
this.parents = new Array(constants_1.TOTAL_NUMBER_OF_CHAINS).fill(undefined);
|
|
93
|
+
this.cache = new Map();
|
|
97
94
|
}
|
|
98
|
-
async getHashesAtHeight(height) {
|
|
99
|
-
const result = await this.nodeProvider.blockflow.getBlockflowHashes({
|
|
100
|
-
fromGroup: this.fromGroup,
|
|
101
|
-
toGroup: this.toGroup,
|
|
102
|
-
height
|
|
103
|
-
});
|
|
95
|
+
async getHashesAtHeight(fromGroup, toGroup, height) {
|
|
96
|
+
const result = await this.nodeProvider.blockflow.getBlockflowHashes({ fromGroup, toGroup, height });
|
|
104
97
|
return result.headers;
|
|
105
98
|
}
|
|
106
99
|
async getBlockByHash(hash) {
|
|
107
100
|
return await this.nodeProvider.blockflow.getBlockflowBlocksBlockHash(hash);
|
|
108
101
|
}
|
|
109
|
-
async
|
|
102
|
+
async getMissingBlocksAndHandleReorg(fromHash, fromHeight, toBlock) {
|
|
103
|
+
const blocks = [];
|
|
104
|
+
let lastBlock = toBlock;
|
|
105
|
+
while (lastBlock.height - 1 > fromHeight) {
|
|
106
|
+
const parentHash = this.getParentHash(lastBlock);
|
|
107
|
+
const block = await this.getBlockByHash(parentHash);
|
|
108
|
+
blocks.push(block);
|
|
109
|
+
lastBlock = block;
|
|
110
|
+
}
|
|
111
|
+
const parentHash = this.getParentHash(lastBlock);
|
|
112
|
+
if (parentHash !== fromHash) {
|
|
113
|
+
await this.handleReorg(toBlock.chainFrom, toBlock.chainTo, fromHash, parentHash);
|
|
114
|
+
}
|
|
115
|
+
return blocks.reverse();
|
|
116
|
+
}
|
|
117
|
+
async handleBlocks(blocks, now) {
|
|
118
|
+
const allBlocks = [];
|
|
119
|
+
for (let index = 0; index < blocks.length; index += 1) {
|
|
120
|
+
const blocksPerChain = blocks[index].filter((b) => !this.cache.has(b.hash));
|
|
121
|
+
if (blocksPerChain.length === 0)
|
|
122
|
+
continue;
|
|
123
|
+
allBlocks.push(...blocksPerChain);
|
|
124
|
+
const parent = this.parents[index];
|
|
125
|
+
if (parent !== undefined) {
|
|
126
|
+
const missingBlocks = await this.getMissingBlocksAndHandleReorg(parent.hash, parent.height, blocksPerChain[0]);
|
|
127
|
+
allBlocks.push(...missingBlocks);
|
|
128
|
+
}
|
|
129
|
+
const latestBlock = blocksPerChain[blocksPerChain.length - 1];
|
|
130
|
+
this.parents[index] = { hash: latestBlock.hash, height: latestBlock.height };
|
|
131
|
+
}
|
|
132
|
+
const sortedBlocks = allBlocks.sort((a, b) => a.timestamp - b.timestamp);
|
|
110
133
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
134
|
+
await this.messageCallback(sortedBlocks);
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
const threshold = now - EXPIRE_DURATION;
|
|
138
|
+
Array.from(this.cache.entries()).forEach(([hash, ts]) => {
|
|
139
|
+
if (ts < threshold)
|
|
140
|
+
this.cache.delete(hash);
|
|
114
141
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (this.parentBlockHash !== undefined && this.getParentHash(block) !== this.parentBlockHash) {
|
|
119
|
-
await this.handleReorg(this.parentBlockHash, this.currentBlockHeight - 1);
|
|
120
|
-
}
|
|
121
|
-
await this.messageCallback(block);
|
|
122
|
-
this.currentBlockHeight += 1;
|
|
123
|
-
this.parentBlockHash = hashes[0];
|
|
142
|
+
const index = sortedBlocks.findIndex((b) => b.timestamp >= threshold);
|
|
143
|
+
if (index !== -1) {
|
|
144
|
+
sortedBlocks.slice(index).forEach((b) => this.cache.set(b.hash, b.timestamp));
|
|
124
145
|
}
|
|
125
146
|
}
|
|
126
|
-
|
|
127
|
-
|
|
147
|
+
}
|
|
148
|
+
async polling() {
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
if (this.fromTimeStamp >= now)
|
|
151
|
+
return;
|
|
152
|
+
while (this.fromTimeStamp < now) {
|
|
153
|
+
if (this.isCancelled())
|
|
154
|
+
return;
|
|
155
|
+
const toTs = Math.min(this.fromTimeStamp + DEFAULT_INTERVAL, now);
|
|
156
|
+
try {
|
|
157
|
+
const result = await this.nodeProvider.blockflow.getBlockflowBlocks({ fromTs: this.fromTimeStamp, toTs });
|
|
158
|
+
await this.handleBlocks(result.blocks, now);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
await this.errorCallback(err, this);
|
|
162
|
+
}
|
|
163
|
+
if (this.fromTimeStamp + EXPIRE_DURATION < now) {
|
|
164
|
+
this.fromTimeStamp = Math.min(toTs + 1, now - EXPIRE_DURATION);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
128
169
|
}
|
|
129
170
|
}
|
|
130
171
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alephium/web3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.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",
|
|
7
7
|
"browser": "dist/alephium-web3.min.js",
|
|
8
8
|
"types": "dist/src/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
|
-
"node":
|
|
11
|
-
|
|
10
|
+
"node": {
|
|
11
|
+
"types": "./dist/src/index.d.ts",
|
|
12
|
+
"default": "./dist/src/index.js"
|
|
13
|
+
},
|
|
14
|
+
"default": {
|
|
15
|
+
"types": "./dist/src/index.d.ts",
|
|
16
|
+
"default": "./dist/alephium-web3.min.js"
|
|
17
|
+
}
|
|
12
18
|
},
|
|
13
19
|
"typesVersions": {
|
|
14
20
|
"*": {
|
|
@@ -27,8 +33,8 @@
|
|
|
27
33
|
},
|
|
28
34
|
"author": "Alephium dev <dev@alephium.org>",
|
|
29
35
|
"config": {
|
|
30
|
-
"alephium_version": "
|
|
31
|
-
"explorer_backend_version": "1.
|
|
36
|
+
"alephium_version": "3.1.0",
|
|
37
|
+
"explorer_backend_version": "1.19.3"
|
|
32
38
|
},
|
|
33
39
|
"type": "commonjs",
|
|
34
40
|
"dependencies": {
|
package/src/address/address.ts
CHANGED
|
@@ -28,6 +28,7 @@ import { MultiSig, lockupScriptCodec } from '../codec/lockup-script-codec'
|
|
|
28
28
|
import { compactSignedIntCodec } from '../codec'
|
|
29
29
|
|
|
30
30
|
const ec = new EC('secp256k1')
|
|
31
|
+
const PublicKeyHashSize = 32
|
|
31
32
|
|
|
32
33
|
export enum AddressType {
|
|
33
34
|
P2PKH = 0x00,
|
|
@@ -59,10 +60,13 @@ function decodeAndValidateAddress(address: string): Uint8Array {
|
|
|
59
60
|
}
|
|
60
61
|
const n = multisig.publicKeyHashes.value.length
|
|
61
62
|
const m = compactSignedIntCodec.toI32(multisig.m)
|
|
62
|
-
if (n < m) {
|
|
63
|
+
if (n < m || m <= 0) {
|
|
63
64
|
throw new Error(`Invalid multisig address, n: ${n}, m: ${m}`)
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
const encodedNSize = compactSignedIntCodec.encodeI32(n).length
|
|
67
|
+
const encodedMSize = multisig.m.rest.length + 1
|
|
68
|
+
const size = encodedNSize + PublicKeyHashSize * n + encodedMSize + 1 // 1 for the P2MPKH prefix
|
|
69
|
+
if (decoded.length === size) return decoded
|
|
66
70
|
} else if (addressType === AddressType.P2PKH || addressType === AddressType.P2SH || addressType === AddressType.P2C) {
|
|
67
71
|
// [type, ...hash]
|
|
68
72
|
if (decoded.length === 33) return decoded
|