@alephium/web3 1.7.2 → 1.7.4
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/api/api-alephium.d.ts +114 -1
- package/dist/src/api/api-alephium.js +30 -1
- package/dist/src/api/api-explorer.d.ts +55 -0
- package/dist/src/api/api-explorer.js +28 -0
- package/dist/src/contract/contract.d.ts +3 -1
- package/dist/src/contract/contract.js +4 -2
- 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 +4 -0
- package/dist/src/utils/utils.js +9 -1
- package/package.json +4 -4
- package/src/address/address.ts +24 -18
- package/src/api/api-alephium.ts +144 -1
- package/src/api/api-explorer.ts +79 -0
- package/src/contract/contract.ts +5 -2
- package/src/signer/tx-builder.ts +14 -9
- package/src/transaction/utils.ts +26 -0
- package/src/utils/utils.ts +16 -0
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/api/api-alephium.ts
CHANGED
|
@@ -926,6 +926,97 @@ export interface RevealMnemonicResult {
|
|
|
926
926
|
mnemonic: string
|
|
927
927
|
}
|
|
928
928
|
|
|
929
|
+
/** RichAssetInput */
|
|
930
|
+
export interface RichAssetInput {
|
|
931
|
+
/** @format int32 */
|
|
932
|
+
hint: number
|
|
933
|
+
/** @format 32-byte-hash */
|
|
934
|
+
key: string
|
|
935
|
+
/** @format hex-string */
|
|
936
|
+
unlockScript: string
|
|
937
|
+
/** @format uint256 */
|
|
938
|
+
attoAlphAmount: string
|
|
939
|
+
/** @format address */
|
|
940
|
+
address: string
|
|
941
|
+
tokens: Token[]
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/** RichBlockAndEvents */
|
|
945
|
+
export interface RichBlockAndEvents {
|
|
946
|
+
block: RichBlockEntry
|
|
947
|
+
events: ContractEventByBlockHash[]
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
/** RichBlockEntry */
|
|
951
|
+
export interface RichBlockEntry {
|
|
952
|
+
/** @format block-hash */
|
|
953
|
+
hash: string
|
|
954
|
+
/** @format int64 */
|
|
955
|
+
timestamp: number
|
|
956
|
+
/** @format int32 */
|
|
957
|
+
chainFrom: number
|
|
958
|
+
/** @format int32 */
|
|
959
|
+
chainTo: number
|
|
960
|
+
/** @format int32 */
|
|
961
|
+
height: number
|
|
962
|
+
deps: string[]
|
|
963
|
+
transactions: RichTransaction[]
|
|
964
|
+
/** @format hex-string */
|
|
965
|
+
nonce: string
|
|
966
|
+
version: number
|
|
967
|
+
/** @format 32-byte-hash */
|
|
968
|
+
depStateHash: string
|
|
969
|
+
/** @format 32-byte-hash */
|
|
970
|
+
txsHash: string
|
|
971
|
+
/** @format hex-string */
|
|
972
|
+
target: string
|
|
973
|
+
ghostUncles: GhostUncleBlockEntry[]
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/** RichBlocksAndEventsPerTimeStampRange */
|
|
977
|
+
export interface RichBlocksAndEventsPerTimeStampRange {
|
|
978
|
+
blocksAndEvents: RichBlockAndEvents[][]
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/** RichContractInput */
|
|
982
|
+
export interface RichContractInput {
|
|
983
|
+
/** @format int32 */
|
|
984
|
+
hint: number
|
|
985
|
+
/** @format 32-byte-hash */
|
|
986
|
+
key: string
|
|
987
|
+
/** @format uint256 */
|
|
988
|
+
attoAlphAmount: string
|
|
989
|
+
/** @format address */
|
|
990
|
+
address: string
|
|
991
|
+
tokens: Token[]
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/** RichTransaction */
|
|
995
|
+
export interface RichTransaction {
|
|
996
|
+
unsigned: RichUnsignedTx
|
|
997
|
+
scriptExecutionOk: boolean
|
|
998
|
+
contractInputs: RichContractInput[]
|
|
999
|
+
generatedOutputs: Output[]
|
|
1000
|
+
inputSignatures: string[]
|
|
1001
|
+
scriptSignatures: string[]
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/** RichUnsignedTx */
|
|
1005
|
+
export interface RichUnsignedTx {
|
|
1006
|
+
/** @format 32-byte-hash */
|
|
1007
|
+
txId: string
|
|
1008
|
+
version: number
|
|
1009
|
+
networkId: number
|
|
1010
|
+
/** @format script */
|
|
1011
|
+
scriptOpt?: string
|
|
1012
|
+
/** @format int32 */
|
|
1013
|
+
gasAmount: number
|
|
1014
|
+
/** @format uint256 */
|
|
1015
|
+
gasPrice: string
|
|
1016
|
+
inputs: RichAssetInput[]
|
|
1017
|
+
fixedOutputs: FixedAssetOutput[]
|
|
1018
|
+
}
|
|
1019
|
+
|
|
929
1020
|
/** Script */
|
|
930
1021
|
export interface Script {
|
|
931
1022
|
code: string
|
|
@@ -1512,7 +1603,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
1512
1603
|
|
|
1513
1604
|
/**
|
|
1514
1605
|
* @title Alephium API
|
|
1515
|
-
* @version 3.
|
|
1606
|
+
* @version 3.7.0
|
|
1516
1607
|
* @baseUrl ../
|
|
1517
1608
|
*/
|
|
1518
1609
|
export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
|
|
@@ -2169,6 +2260,40 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
2169
2260
|
...params
|
|
2170
2261
|
}).then(convertHttpResponse),
|
|
2171
2262
|
|
|
2263
|
+
/**
|
|
2264
|
+
* No description
|
|
2265
|
+
*
|
|
2266
|
+
* @tags Blockflow
|
|
2267
|
+
* @name GetBlockflowRichBlocks
|
|
2268
|
+
* @summary Given a time interval, list blocks containing events and transactions with enriched input information when node indexes are enabled.
|
|
2269
|
+
* @request GET:/blockflow/rich-blocks
|
|
2270
|
+
*/
|
|
2271
|
+
getBlockflowRichBlocks: (
|
|
2272
|
+
query: {
|
|
2273
|
+
/**
|
|
2274
|
+
* @format int64
|
|
2275
|
+
* @min 0
|
|
2276
|
+
*/
|
|
2277
|
+
fromTs: number
|
|
2278
|
+
/**
|
|
2279
|
+
* @format int64
|
|
2280
|
+
* @min 0
|
|
2281
|
+
*/
|
|
2282
|
+
toTs?: number
|
|
2283
|
+
},
|
|
2284
|
+
params: RequestParams = {}
|
|
2285
|
+
) =>
|
|
2286
|
+
this.request<
|
|
2287
|
+
RichBlocksAndEventsPerTimeStampRange,
|
|
2288
|
+
BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable
|
|
2289
|
+
>({
|
|
2290
|
+
path: `/blockflow/rich-blocks`,
|
|
2291
|
+
method: 'GET',
|
|
2292
|
+
query: query,
|
|
2293
|
+
format: 'json',
|
|
2294
|
+
...params
|
|
2295
|
+
}).then(convertHttpResponse),
|
|
2296
|
+
|
|
2172
2297
|
/**
|
|
2173
2298
|
* No description
|
|
2174
2299
|
*
|
|
@@ -2217,6 +2342,24 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
2217
2342
|
...params
|
|
2218
2343
|
}).then(convertHttpResponse),
|
|
2219
2344
|
|
|
2345
|
+
/**
|
|
2346
|
+
* No description
|
|
2347
|
+
*
|
|
2348
|
+
* @tags Blockflow
|
|
2349
|
+
* @name GetBlockflowRichBlocksBlockHash
|
|
2350
|
+
* @summary Get a block containing events and transactions with enriched input information when node indexes are enabled.
|
|
2351
|
+
* @request GET:/blockflow/rich-blocks/{block_hash}
|
|
2352
|
+
*/
|
|
2353
|
+
getBlockflowRichBlocksBlockHash: (blockHash: string, params: RequestParams = {}) =>
|
|
2354
|
+
this.request<RichBlockAndEvents, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>(
|
|
2355
|
+
{
|
|
2356
|
+
path: `/blockflow/rich-blocks/${blockHash}`,
|
|
2357
|
+
method: 'GET',
|
|
2358
|
+
format: 'json',
|
|
2359
|
+
...params
|
|
2360
|
+
}
|
|
2361
|
+
).then(convertHttpResponse),
|
|
2362
|
+
|
|
2220
2363
|
/**
|
|
2221
2364
|
* No description
|
|
2222
2365
|
*
|
package/src/api/api-explorer.ts
CHANGED
|
@@ -190,6 +190,7 @@ export interface AssetOutput {
|
|
|
190
190
|
|
|
191
191
|
/** NFT */
|
|
192
192
|
export interface NFT {
|
|
193
|
+
id: string
|
|
193
194
|
type: string
|
|
194
195
|
}
|
|
195
196
|
|
|
@@ -217,6 +218,14 @@ export interface AcceptedTransaction {
|
|
|
217
218
|
timestamp: number
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
/** HolderInfo */
|
|
222
|
+
export interface HolderInfo {
|
|
223
|
+
/** @format address */
|
|
224
|
+
address: string
|
|
225
|
+
/** @format uint256 */
|
|
226
|
+
balance: string
|
|
227
|
+
}
|
|
228
|
+
|
|
220
229
|
/** TokenSupply */
|
|
221
230
|
export interface TokenSupply {
|
|
222
231
|
/** @format uint256 */
|
|
@@ -317,6 +326,8 @@ export enum TokenStdInterfaceId {
|
|
|
317
326
|
export interface ExplorerInfo {
|
|
318
327
|
releaseVersion: string
|
|
319
328
|
commit: string
|
|
329
|
+
/** @format int64 */
|
|
330
|
+
lastHoldersUpdate: number
|
|
320
331
|
/** @format int32 */
|
|
321
332
|
migrationsVersion: number
|
|
322
333
|
/** @format int64 */
|
|
@@ -367,6 +378,7 @@ export interface Transaction {
|
|
|
367
378
|
|
|
368
379
|
/** FungibleToken */
|
|
369
380
|
export interface FungibleToken {
|
|
381
|
+
id: string
|
|
370
382
|
type: string
|
|
371
383
|
}
|
|
372
384
|
|
|
@@ -1588,6 +1600,40 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
1588
1600
|
...params
|
|
1589
1601
|
}).then(convertHttpResponse),
|
|
1590
1602
|
|
|
1603
|
+
/**
|
|
1604
|
+
* @description Get a sorted list of top addresses by {token_id} balance. Updates once per day.
|
|
1605
|
+
*
|
|
1606
|
+
* @tags Tokens
|
|
1607
|
+
* @name GetTokensHoldersTokenTokenId
|
|
1608
|
+
* @request GET:/tokens/holders/token/{token_id}
|
|
1609
|
+
*/
|
|
1610
|
+
getTokensHoldersTokenTokenId: (
|
|
1611
|
+
tokenId: string,
|
|
1612
|
+
query?: {
|
|
1613
|
+
/**
|
|
1614
|
+
* Page number
|
|
1615
|
+
* @format int32
|
|
1616
|
+
* @min 1
|
|
1617
|
+
*/
|
|
1618
|
+
page?: number
|
|
1619
|
+
/**
|
|
1620
|
+
* Number of items per page
|
|
1621
|
+
* @format int32
|
|
1622
|
+
* @min 0
|
|
1623
|
+
* @max 100
|
|
1624
|
+
*/
|
|
1625
|
+
limit?: number
|
|
1626
|
+
},
|
|
1627
|
+
params: RequestParams = {}
|
|
1628
|
+
) =>
|
|
1629
|
+
this.request<HolderInfo[], BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
1630
|
+
path: `/tokens/holders/token/${tokenId}`,
|
|
1631
|
+
method: 'GET',
|
|
1632
|
+
query: query,
|
|
1633
|
+
format: 'json',
|
|
1634
|
+
...params
|
|
1635
|
+
}).then(convertHttpResponse),
|
|
1636
|
+
|
|
1591
1637
|
/**
|
|
1592
1638
|
* @description List token transactions
|
|
1593
1639
|
*
|
|
@@ -1676,6 +1722,39 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
1676
1722
|
...params
|
|
1677
1723
|
}).then(convertHttpResponse),
|
|
1678
1724
|
|
|
1725
|
+
/**
|
|
1726
|
+
* @description Get a sorted list of top addresses by ALPH balance. Updates once per day.
|
|
1727
|
+
*
|
|
1728
|
+
* @tags Tokens
|
|
1729
|
+
* @name GetTokensHoldersAlph
|
|
1730
|
+
* @request GET:/tokens/holders/alph
|
|
1731
|
+
*/
|
|
1732
|
+
getTokensHoldersAlph: (
|
|
1733
|
+
query?: {
|
|
1734
|
+
/**
|
|
1735
|
+
* Page number
|
|
1736
|
+
* @format int32
|
|
1737
|
+
* @min 1
|
|
1738
|
+
*/
|
|
1739
|
+
page?: number
|
|
1740
|
+
/**
|
|
1741
|
+
* Number of items per page
|
|
1742
|
+
* @format int32
|
|
1743
|
+
* @min 0
|
|
1744
|
+
* @max 100
|
|
1745
|
+
*/
|
|
1746
|
+
limit?: number
|
|
1747
|
+
},
|
|
1748
|
+
params: RequestParams = {}
|
|
1749
|
+
) =>
|
|
1750
|
+
this.request<HolderInfo[], BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
1751
|
+
path: `/tokens/holders/alph`,
|
|
1752
|
+
method: 'GET',
|
|
1753
|
+
query: query,
|
|
1754
|
+
format: 'json',
|
|
1755
|
+
...params
|
|
1756
|
+
}).then(convertHttpResponse),
|
|
1757
|
+
|
|
1679
1758
|
/**
|
|
1680
1759
|
* @description Return metadata for the given nft tokens, if metadata doesn't exist or token isn't a nft, it won't be in the output list
|
|
1681
1760
|
*
|
package/src/contract/contract.ts
CHANGED
|
@@ -2046,12 +2046,14 @@ function toFieldsSig(contractName: string, functionSig: FunctionSig): FieldsSig
|
|
|
2046
2046
|
}
|
|
2047
2047
|
}
|
|
2048
2048
|
|
|
2049
|
+
type Calls = Record<string, Optional<CallContractParams<any>, 'args'>>
|
|
2049
2050
|
export async function multicallMethods<I extends ContractInstance, F extends Fields>(
|
|
2050
2051
|
contract: ContractFactory<I, F>,
|
|
2051
2052
|
instance: ContractInstance,
|
|
2052
|
-
|
|
2053
|
+
_callss: Calls | Calls[],
|
|
2053
2054
|
getContractByCodeHash: (codeHash: string) => Contract
|
|
2054
2055
|
): Promise<Record<string, CallContractResult<any>>[] | Record<string, CallContractResult<any>>> {
|
|
2056
|
+
const callss = Array.isArray(_callss) ? _callss : [_callss]
|
|
2055
2057
|
const callEntries = callss.map((calls) => Object.entries(calls))
|
|
2056
2058
|
const callsParams = callEntries.map((entries) => {
|
|
2057
2059
|
return entries.map((entry) => {
|
|
@@ -2068,7 +2070,7 @@ export async function multicallMethods<I extends ContractInstance, F extends Fie
|
|
|
2068
2070
|
})
|
|
2069
2071
|
const result = await getCurrentNodeProvider().contracts.postContractsMulticallContract({ calls: callsParams.flat() })
|
|
2070
2072
|
let callResultIndex = 0
|
|
2071
|
-
|
|
2073
|
+
const results = callsParams.map((calls, index0) => {
|
|
2072
2074
|
const callsResult: Record<string, CallContractResult<any>> = {}
|
|
2073
2075
|
const entries = callEntries[`${index0}`]
|
|
2074
2076
|
calls.forEach((call, index1) => {
|
|
@@ -2085,6 +2087,7 @@ export async function multicallMethods<I extends ContractInstance, F extends Fie
|
|
|
2085
2087
|
})
|
|
2086
2088
|
return callsResult
|
|
2087
2089
|
})
|
|
2090
|
+
return Array.isArray(_callss) ? results : results[0]
|
|
2088
2091
|
}
|
|
2089
2092
|
|
|
2090
2093
|
export async function getContractEventsCurrentCount(contractAddress: Address): Promise<number> {
|
package/src/signer/tx-builder.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 { binToHex } from '../utils'
|
|
19
|
+
import { binToHex, hexToBinUnsafe } from '../utils'
|
|
20
20
|
import { fromApiNumber256, node, NodeProvider, toApiNumber256Optional, toApiTokens } from '../api'
|
|
21
21
|
import { addressFromPublicKey, contractIdFromAddress } from '../address'
|
|
22
22
|
import { toApiDestinations } from './signer'
|
|
@@ -32,6 +32,9 @@ import {
|
|
|
32
32
|
SignUnsignedTxParams,
|
|
33
33
|
SignUnsignedTxResult
|
|
34
34
|
} from './types'
|
|
35
|
+
import { unsignedTxCodec, UnsignedTxCodec } from '../codec'
|
|
36
|
+
import { groupIndexOfTransaction } from '../transaction'
|
|
37
|
+
import { blakeHash } from '../codec/hash'
|
|
35
38
|
|
|
36
39
|
export abstract class TransactionBuilder {
|
|
37
40
|
abstract get nodeProvider(): NodeProvider
|
|
@@ -113,16 +116,18 @@ export abstract class TransactionBuilder {
|
|
|
113
116
|
return { ...response, groupIndex: response.fromGroup, gasPrice: fromApiNumber256(response.gasPrice) }
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
const decoded =
|
|
119
|
+
buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'> {
|
|
120
|
+
const unsignedTxBin = hexToBinUnsafe(params.unsignedTx)
|
|
121
|
+
const decoded = unsignedTxCodec.decode(unsignedTxBin)
|
|
122
|
+
const txId = binToHex(blakeHash(unsignedTxBin))
|
|
123
|
+
const [fromGroup, toGroup] = groupIndexOfTransaction(decoded)
|
|
119
124
|
return {
|
|
120
|
-
fromGroup:
|
|
121
|
-
toGroup:
|
|
125
|
+
fromGroup: fromGroup,
|
|
126
|
+
toGroup: toGroup,
|
|
122
127
|
unsignedTx: params.unsignedTx,
|
|
123
|
-
txId:
|
|
124
|
-
gasAmount: decoded.
|
|
125
|
-
gasPrice:
|
|
128
|
+
txId: txId,
|
|
129
|
+
gasAmount: decoded.gasAmount,
|
|
130
|
+
gasPrice: decoded.gasPrice
|
|
126
131
|
}
|
|
127
132
|
}
|
|
128
133
|
}
|
package/src/transaction/utils.ts
CHANGED
|
@@ -16,8 +16,12 @@ 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 { groupOfLockupScript } from '../address'
|
|
19
20
|
import { node } from '../api'
|
|
21
|
+
import { UnsignedTx } from '../codec'
|
|
22
|
+
import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
20
23
|
import { getCurrentNodeProvider } from '../global'
|
|
24
|
+
import { xorByte } from '../utils'
|
|
21
25
|
|
|
22
26
|
function isConfirmed(txStatus: node.TxStatus): txStatus is node.Confirmed {
|
|
23
27
|
return txStatus.type === 'Confirmed'
|
|
@@ -36,3 +40,25 @@ export async function waitForTxConfirmation(
|
|
|
36
40
|
await new Promise((r) => setTimeout(r, requestInterval))
|
|
37
41
|
return waitForTxConfirmation(txId, confirmations, requestInterval)
|
|
38
42
|
}
|
|
43
|
+
|
|
44
|
+
export function groupIndexOfTransaction(unsignedTx: UnsignedTx): [number, number] {
|
|
45
|
+
if (unsignedTx.inputs.length === 0) throw new Error('Empty inputs for unsignedTx')
|
|
46
|
+
|
|
47
|
+
const fromGroup = groupFromHint(unsignedTx.inputs[0].hint)
|
|
48
|
+
|
|
49
|
+
let toGroup = fromGroup
|
|
50
|
+
for (const output of unsignedTx.fixedOutputs) {
|
|
51
|
+
const outputGroup = groupOfLockupScript(output.lockupScript)
|
|
52
|
+
if (outputGroup !== fromGroup) {
|
|
53
|
+
toGroup = outputGroup
|
|
54
|
+
break
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return [fromGroup, toGroup]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function groupFromHint(hint: number): number {
|
|
62
|
+
const hash = xorByte(hint)
|
|
63
|
+
return hash % TOTAL_NUMBER_OF_GROUPS
|
|
64
|
+
}
|
package/src/utils/utils.ts
CHANGED
|
@@ -156,8 +156,24 @@ export function concatBytes(arrays: Uint8Array[]): Uint8Array {
|
|
|
156
156
|
return result
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
export function xorByte(intValue: number): number {
|
|
160
|
+
const byte0 = (intValue >> 24) & 0xff
|
|
161
|
+
const byte1 = (intValue >> 16) & 0xff
|
|
162
|
+
const byte2 = (intValue >> 8) & 0xff
|
|
163
|
+
const byte3 = intValue & 0xff
|
|
164
|
+
return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff
|
|
165
|
+
}
|
|
166
|
+
|
|
159
167
|
type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
|
|
160
168
|
export type Eq<X, Y> = _Eq<{ [P in keyof X]: X[P] }, { [P in keyof Y]: Y[P] }>
|
|
161
169
|
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
|
|
162
170
|
export function assertType<T extends true>(): void {}
|
|
163
171
|
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
|
|
172
|
+
|
|
173
|
+
export type Narrow<type> =
|
|
174
|
+
| (unknown extends type ? unknown : never)
|
|
175
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
176
|
+
| (type extends Function ? type : never)
|
|
177
|
+
| (type extends bigint | boolean | number | string ? type : never)
|
|
178
|
+
| (type extends [] ? [] : never)
|
|
179
|
+
| { [K in keyof type]: Narrow<type[K]> }
|