-
Notifications
You must be signed in to change notification settings - Fork 59
/
index.ts
123 lines (113 loc) · 3.96 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import {
decode, encode, Encoded, Encoding,
} from '../../utils/encoder';
import { hash } from '../../utils/crypto';
import { Field } from './field-types';
import { txSchema } from './schema';
import { TxUnpacked, TxParams, TxParamsAsync } from './schema.generated';
import { Tag } from './constants';
import { buildContractId } from './helpers';
import { getSchema as getSchemaCommon, packRecord, unpackRecord } from './common';
import { ArgumentError } from '../../utils/errors';
/**
* JavaScript-based Transaction builder
*/
export function getSchema(tag: Tag, version?: number): Array<[string, Field]> {
return getSchemaCommon(txSchema, Tag, tag, version);
}
type TxEncoding = Encoding.Transaction | Encoding.Poi | Encoding.StateTrees
| Encoding.CallStateTree;
/**
* Build transaction
* @category transaction builder
* @param params - Transaction params
*/
export function buildTx(params: TxParams): Encoded.Transaction;
/**
* Build node entry with a custom encoding
* @param params - Entry params
* @param options - Options
* @param options.prefix - Output encoding
*/
export function buildTx<E extends TxEncoding>(
params: TxParams,
{ prefix }: { prefix: E },
): Encoded.Generic<E>;
export function buildTx(
params: TxParams,
{ prefix }: { prefix?: TxEncoding } = {},
): Encoded.Generic<TxEncoding> {
return packRecord(txSchema, Tag, params, {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
unpackTx,
buildTx,
rebuildTx: (overrideParams: any) => buildTx(
{ ...params, ...overrideParams },
),
}, prefix ?? Encoding.Transaction);
}
export type BuildTxOptions <TxType extends Tag, OmitFields extends string> =
Omit<TxParamsAsync & { tag: TxType }, 'tag' | OmitFields>;
// TODO: require onNode because it is the only reason this builder is async [breaking change]
/**
* Build transaction async (may request node for additional data)
* @category transaction builder
* @param params - Transaction params
* @returns tx_-encoded transaction
*/
export async function buildTxAsync(params: TxParamsAsync): Promise<Encoded.Transaction> {
await Promise.all(
getSchema(params.tag, params.version)
.map(async ([key, field]) => {
if (field.prepare == null) return;
// @ts-expect-error the type of `params[key]` can't be determined accurately
params[key] = await field.prepare(params[key], params, params);
}),
);
// @ts-expect-error after preparation properties should be compatible with sync tx builder
return buildTx(params);
}
/**
* Unpack transaction encoded as string
* @category transaction builder
* @param encodedTx - Encoded transaction
* @param txType - Expected transaction type
* @returns Transaction params
*/
export function unpackTx<TxType extends Tag>(
encodedTx: Encoded.Generic<TxEncoding>,
txType?: TxType,
): TxUnpacked & { tag: TxType } {
return unpackRecord(txSchema, Tag, encodedTx, txType, {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
unpackTx,
}) as any;
}
/**
* Build a transaction hash
* @category transaction builder
* @param rawTx - base64 or rlp encoded transaction
* @returns Transaction hash
*/
export function buildTxHash(rawTx: Encoded.Transaction | Uint8Array): Encoded.TxHash {
const data = typeof rawTx === 'string' && rawTx.startsWith('tx_')
? decode(rawTx)
: rawTx;
return encode(hash(data), Encoding.TxHash);
}
/**
* Build a contract public key by contractCreateTx, gaAttach or signedTx
* @category contract
* @param contractTx - Transaction
* @returns Contract public key
*/
export function buildContractIdByContractTx(
contractTx: Encoded.Transaction,
): Encoded.ContractAddress {
let params = unpackTx(contractTx);
if (Tag.SignedTx === params.tag) params = params.encodedTx;
if (Tag.ContractCreateTx !== params.tag && Tag.GaAttachTx !== params.tag) {
throw new ArgumentError('contractTx', 'a contractCreateTx or gaAttach', params.tag);
}
return buildContractId(params.ownerId, params.nonce);
}