@effectstream/sync 0.100.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/package.json +29 -0
- package/src/mod.ts +3 -0
- package/src/sync-protocols/avail/AvailClient.ts +120 -0
- package/src/sync-protocols/avail/fetcher.ts +174 -0
- package/src/sync-protocols/avail/state.ts +134 -0
- package/src/sync-protocols/avail/types.ts +92 -0
- package/src/sync-protocols/base/fetcher.ts +43 -0
- package/src/sync-protocols/base/page.ts +89 -0
- package/src/sync-protocols/base/primitive.ts +24 -0
- package/src/sync-protocols/base/state.ts +143 -0
- package/src/sync-protocols/bitcoin/fetcher.ts +549 -0
- package/src/sync-protocols/bitcoin/state.ts +144 -0
- package/src/sync-protocols/bitcoin/types.ts +92 -0
- package/src/sync-protocols/celestia/CelestiaClient.ts +139 -0
- package/src/sync-protocols/celestia/fetcher.ts +165 -0
- package/src/sync-protocols/celestia/state.ts +131 -0
- package/src/sync-protocols/celestia/types.ts +46 -0
- package/src/sync-protocols/common/page-helpers.ts +65 -0
- package/src/sync-protocols/common/root.ts +35 -0
- package/src/sync-protocols/common/utils.ts +29 -0
- package/src/sync-protocols/evm/fetcher.ts +290 -0
- package/src/sync-protocols/evm/state.ts +122 -0
- package/src/sync-protocols/evm/types.ts +53 -0
- package/src/sync-protocols/midnight/MidnightClient.ts +210 -0
- package/src/sync-protocols/midnight/fetcher.ts +252 -0
- package/src/sync-protocols/midnight/state.ts +147 -0
- package/src/sync-protocols/midnight/types.ts +128 -0
- package/src/sync-protocols/midnight/zswap-decoder.ts +123 -0
- package/src/sync-protocols/mod.ts +29 -0
- package/src/sync-protocols/near/NearClient.ts +178 -0
- package/src/sync-protocols/near/fetcher.ts +274 -0
- package/src/sync-protocols/near/state.ts +130 -0
- package/src/sync-protocols/near/types.ts +46 -0
- package/src/sync-protocols/ntp/fetcher.ts +199 -0
- package/src/sync-protocols/ntp/state.ts +118 -0
- package/src/sync-protocols/ntp/types.ts +40 -0
- package/src/sync-protocols/orchestration/merge.ts +215 -0
- package/src/sync-protocols/orchestration/sync.ts +74 -0
- package/src/sync-protocols/types.ts +32 -0
- package/src/sync-protocols/utxorpc/BufferedRpc.ts +169 -0
- package/src/sync-protocols/utxorpc/fetcher.ts +116 -0
- package/src/sync-protocols/utxorpc/state.ts +186 -0
- package/src/sync-protocols/utxorpc/types.ts +53 -0
- package/src/sync-protocols/utxorpc/utils.ts +80 -0
- package/src/syncProtocolFactory.ts +149 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BlockNumber,
|
|
3
|
+
MidnightAddress,
|
|
4
|
+
MidnightBlockHash,
|
|
5
|
+
MidnightBlockNumber,
|
|
6
|
+
MidnightTxHash,
|
|
7
|
+
TimestampIso8601,
|
|
8
|
+
TimestampMs,
|
|
9
|
+
} from "@effectstream/utils";
|
|
10
|
+
import type {
|
|
11
|
+
ConfigNetworkType,
|
|
12
|
+
ConfigSyncProtocolType,
|
|
13
|
+
FlattenSyncProtocolIOFor,
|
|
14
|
+
PrimitiveEntry,
|
|
15
|
+
SyncProtocolWithNetwork,
|
|
16
|
+
} from "@effectstream/config";
|
|
17
|
+
import type { MidnightGqlBlockState } from "./MidnightClient.ts";
|
|
18
|
+
|
|
19
|
+
export type CommonFunnelArgs = {
|
|
20
|
+
/**
|
|
21
|
+
* TODO: right now the Midnight funnels works in an odd way
|
|
22
|
+
* where we fetch every single block in one large graphql query
|
|
23
|
+
* then parse into it as needed
|
|
24
|
+
* Not clear this is the best approach
|
|
25
|
+
*/
|
|
26
|
+
block: CachedBlock;
|
|
27
|
+
fromBlock: BlockNumber;
|
|
28
|
+
toBlock: BlockNumber;
|
|
29
|
+
toMainchainBlockNumber?: (block: BlockNumber) => BlockNumber;
|
|
30
|
+
toMainchainTimestamp?: (block: BlockNumber) => TimestampMs;
|
|
31
|
+
isPresync: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// =============
|
|
35
|
+
// Graphql Block
|
|
36
|
+
// =============
|
|
37
|
+
|
|
38
|
+
// Interfaces approximated from GraphQL schema served by indexer v1.3.1
|
|
39
|
+
|
|
40
|
+
interface ContractCallOrDeploy {
|
|
41
|
+
address: MidnightAddress;
|
|
42
|
+
state: string;
|
|
43
|
+
transaction: Transaction;
|
|
44
|
+
zswapChainState: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface ContractCall extends ContractCallOrDeploy {
|
|
48
|
+
deploy: ContractCallOrDeploy;
|
|
49
|
+
operation: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface ContractDeploy extends ContractCallOrDeploy {
|
|
53
|
+
definition: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface Transaction {
|
|
57
|
+
block: Block;
|
|
58
|
+
hash: MidnightTxHash;
|
|
59
|
+
identifiers: string[];
|
|
60
|
+
contractCalls: (ContractCall | ContractDeploy)[];
|
|
61
|
+
raw: string;
|
|
62
|
+
applyStage: string;
|
|
63
|
+
merkleTreeRoot?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ZswapLedgerEvent {
|
|
67
|
+
id: number;
|
|
68
|
+
raw: string;
|
|
69
|
+
maxId: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface Block {
|
|
73
|
+
hash: MidnightBlockHash;
|
|
74
|
+
height: MidnightBlockNumber;
|
|
75
|
+
protocolVersion: number;
|
|
76
|
+
timestamp: TimestampIso8601;
|
|
77
|
+
parent: {
|
|
78
|
+
hash: MidnightBlockHash;
|
|
79
|
+
};
|
|
80
|
+
transactions: {
|
|
81
|
+
hash: MidnightTxHash;
|
|
82
|
+
contractActions: {
|
|
83
|
+
address: MidnightAddress;
|
|
84
|
+
state: string;
|
|
85
|
+
}[];
|
|
86
|
+
zswapLedgerEvents?: ZswapLedgerEvent[];
|
|
87
|
+
}[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type CachedBlock = Pick<Block, "height" | "hash" | "timestamp"> & {
|
|
91
|
+
transactions: (Pick<Transaction, "hash"> & {
|
|
92
|
+
contractCalls: Pick<ContractCall, "address" | "state">[];
|
|
93
|
+
})[];
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
import type { PageRelation } from "../base/page.ts";
|
|
97
|
+
import type { PageSyncRange } from "../common/page-helpers.ts";
|
|
98
|
+
|
|
99
|
+
export type Page = {
|
|
100
|
+
height: BlockNumber;
|
|
101
|
+
hash: MidnightBlockHash;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type PrimitiveType = FlattenSyncProtocolIOFor<
|
|
105
|
+
ConfigSyncProtocolType.MIDNIGHT_PARALLEL
|
|
106
|
+
>;
|
|
107
|
+
export type Input = PageSyncRange<BlockNumber>;
|
|
108
|
+
export type Output = {
|
|
109
|
+
raw: Block;
|
|
110
|
+
primitives: PrimitiveType[];
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const pageRelation: PageRelation<Page> = {
|
|
114
|
+
compare: (p1, p2) => p1.height - p2.height,
|
|
115
|
+
equals: (p1, p2) => p1.height === p2.height,
|
|
116
|
+
min: (p1, p2) => (p1.height < p2.height ? p1 : p2),
|
|
117
|
+
max: (p1, p2) => (p1.height > p2.height ? p1 : p2),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export type ConfigType = Extract<
|
|
121
|
+
SyncProtocolWithNetwork,
|
|
122
|
+
{ networkType: ConfigNetworkType.MIDNIGHT }
|
|
123
|
+
>;
|
|
124
|
+
|
|
125
|
+
export type PrimitiveEntryType = Extract<
|
|
126
|
+
PrimitiveEntry,
|
|
127
|
+
{ syncProtocol: ConfigSyncProtocolType.MIDNIGHT_PARALLEL }
|
|
128
|
+
>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import * as ledger from '@midnight-ntwrk/ledger-v8';
|
|
3
|
+
|
|
4
|
+
// TODO This alternative implementation should be the native way to decode the event.
|
|
5
|
+
function new_decodeZswapInputEvent(rawHex: string): ledger.Event | null {
|
|
6
|
+
try {
|
|
7
|
+
const bytes = Uint8Array.from(
|
|
8
|
+
Buffer.from(rawHex.replace(/^0x/, ""), "hex"),
|
|
9
|
+
);
|
|
10
|
+
const event = ledger.Event.deserialize(bytes);
|
|
11
|
+
console.log("event", event);
|
|
12
|
+
// if (event.type === "ZswapInput") {
|
|
13
|
+
// event.nullifier — Uint8Array (32 bytes)
|
|
14
|
+
// event.source.transactionHash
|
|
15
|
+
// event.source.logicalSegment
|
|
16
|
+
// } else if (event.type === "ZswapOutput") {
|
|
17
|
+
// event.commitment, etc.
|
|
18
|
+
// }
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ─── SCALE compact integer decoder ───────────────────────────────────────────
|
|
26
|
+
//
|
|
27
|
+
// Bottom 2 bits of the first byte are the mode:
|
|
28
|
+
// 00 = 1-byte (value in bits [7:2])
|
|
29
|
+
// 01 = 2-byte
|
|
30
|
+
// 10 = 4-byte
|
|
31
|
+
// 11 = n-byte length prefix
|
|
32
|
+
|
|
33
|
+
function readScaleU32(b: Uint8Array, pos: number): [number, number] {
|
|
34
|
+
const first = b[pos];
|
|
35
|
+
const mode = first & 0b11;
|
|
36
|
+
if (mode === 0b00) {
|
|
37
|
+
return [(first & 0xFC) >> 2, pos + 1];
|
|
38
|
+
} else if (mode === 0b01) {
|
|
39
|
+
const second = b[pos + 1];
|
|
40
|
+
const v0 = ((first & 0xFC) >> 2) | ((second & 0x03) << 6);
|
|
41
|
+
const v1 = (second & 0xFC) >> 2;
|
|
42
|
+
return [(v0 | (v1 << 8)) >>> 0, pos + 2];
|
|
43
|
+
} else if (mode === 0b10) {
|
|
44
|
+
const s = b[pos + 1], t = b[pos + 2], u = b[pos + 3];
|
|
45
|
+
const v0 = ((first & 0xFC) >> 2) | ((s & 0x03) << 6);
|
|
46
|
+
const v1 = ((s & 0xFC) >> 2) | ((t & 0x03) << 6);
|
|
47
|
+
const v2 = ((t & 0xFC) >> 2) | ((u & 0x03) << 6);
|
|
48
|
+
const v3 = (u & 0xFC) >> 2;
|
|
49
|
+
return [(v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)) >>> 0, pos + 4];
|
|
50
|
+
} else {
|
|
51
|
+
const n = ((first & 0xFC) >> 2) + 4;
|
|
52
|
+
let val = 0;
|
|
53
|
+
for (let i = 0; i < n; i++) val |= b[pos + 1 + i] << (i * 8);
|
|
54
|
+
return [val >>> 0, pos + 1 + n];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function hexToBytes(hex: string): Uint8Array {
|
|
59
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
60
|
+
const arr = new Uint8Array(clean.length / 2);
|
|
61
|
+
for (let i = 0; i < arr.length; i++) {
|
|
62
|
+
arr[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
63
|
+
}
|
|
64
|
+
return arr;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function bytesToHex(bytes: Uint8Array): string {
|
|
68
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ─── Binary layout for "midnight:event[v9]:" ─────────────────────────────────
|
|
72
|
+
// 19 bytes outer tag "midnight:event[v9]:"
|
|
73
|
+
// 32 bytes EventSource.transaction_hash
|
|
74
|
+
// 2 bytes EventSource.logical_segment (LE u16)
|
|
75
|
+
// 2 bytes EventSource.physical_segment (LE u16, skipped)
|
|
76
|
+
// SCALE u32 EventDetails variant: 0=ZswapInput, 1=ZswapOutput, 2+=other
|
|
77
|
+
//
|
|
78
|
+
// ZswapInput: 4-byte contract_id + 32-byte CoinNullifier
|
|
79
|
+
|
|
80
|
+
const OUTER_TAG = "midnight:event[v9]:";
|
|
81
|
+
|
|
82
|
+
export interface DecodedZswapInput {
|
|
83
|
+
/** 32-byte transaction hash, hex */
|
|
84
|
+
txHash: string;
|
|
85
|
+
/** Logical segment index */
|
|
86
|
+
logicalSegment: number;
|
|
87
|
+
/** 32-byte nullifier, hex */
|
|
88
|
+
nullifier: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Decode a raw SCALE-encoded zswap ledger event.
|
|
93
|
+
* Returns the decoded data if the event is a ZswapInput (nullifier spend),
|
|
94
|
+
* or `null` for ZswapOutput / other variants.
|
|
95
|
+
*/
|
|
96
|
+
export function decodeZswapInputEvent(
|
|
97
|
+
rawHex: string,
|
|
98
|
+
): DecodedZswapInput | null {
|
|
99
|
+
try {
|
|
100
|
+
const b = hexToBytes(rawHex);
|
|
101
|
+
let pos = OUTER_TAG.length;
|
|
102
|
+
|
|
103
|
+
const txHash = bytesToHex(b.slice(pos, pos + 32));
|
|
104
|
+
pos += 32;
|
|
105
|
+
const logicalSegment = b[pos] | (b[pos + 1] << 8);
|
|
106
|
+
pos += 2;
|
|
107
|
+
pos += 2; // skip physical segment
|
|
108
|
+
|
|
109
|
+
const [variant, p1] = readScaleU32(b, pos);
|
|
110
|
+
pos = p1;
|
|
111
|
+
|
|
112
|
+
if (variant !== 0) {
|
|
113
|
+
return null; // ZswapOutput or other — not a nullifier event
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
pos += 4; // skip 4-byte contract_id
|
|
117
|
+
|
|
118
|
+
const nullifier = bytesToHex(b.slice(pos, pos + 32));
|
|
119
|
+
return { txHash, logicalSegment, nullifier };
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export * from "./evm/fetcher.ts";
|
|
2
|
+
export * from "./evm/state.ts";
|
|
3
|
+
|
|
4
|
+
export * from "./midnight/fetcher.ts";
|
|
5
|
+
export * from "./midnight/state.ts";
|
|
6
|
+
|
|
7
|
+
export * from "./avail/fetcher.ts";
|
|
8
|
+
export * from "./avail/state.ts";
|
|
9
|
+
|
|
10
|
+
export * from "./bitcoin/fetcher.ts";
|
|
11
|
+
export * from "./bitcoin/state.ts";
|
|
12
|
+
|
|
13
|
+
export * from "./ntp/fetcher.ts";
|
|
14
|
+
export * from "./ntp/state.ts";
|
|
15
|
+
|
|
16
|
+
export * from "./utxorpc/fetcher.ts";
|
|
17
|
+
export * from "./utxorpc/state.ts";
|
|
18
|
+
|
|
19
|
+
export * from "./celestia/fetcher.ts";
|
|
20
|
+
export * from "./celestia/state.ts";
|
|
21
|
+
|
|
22
|
+
export type * from "./base/fetcher.ts";
|
|
23
|
+
export type * from "./base/state.ts";
|
|
24
|
+
export * from "./orchestration/merge.ts";
|
|
25
|
+
export * from "./orchestration/sync.ts";
|
|
26
|
+
|
|
27
|
+
export { chainPageRelation } from "./common/root.ts";
|
|
28
|
+
// TODO: remove
|
|
29
|
+
export type { ChainBlock } from "./common/root.ts";
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// ============================
|
|
2
|
+
// NEAR JSON-RPC type responses
|
|
3
|
+
// ============================
|
|
4
|
+
|
|
5
|
+
export type NearBlockHeader = {
|
|
6
|
+
height: number;
|
|
7
|
+
hash: string;
|
|
8
|
+
/** Nanosecond timestamp */
|
|
9
|
+
timestamp: number;
|
|
10
|
+
/** Nanosecond timestamp as string in some APIs */
|
|
11
|
+
timestamp_nanosec: string;
|
|
12
|
+
chunks_included: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type NearBlockChunkHeader = {
|
|
16
|
+
chunk_hash: string;
|
|
17
|
+
shard_id: number;
|
|
18
|
+
height_included: number;
|
|
19
|
+
tx_root: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type NearBlock = {
|
|
23
|
+
header: NearBlockHeader;
|
|
24
|
+
chunks: NearBlockChunkHeader[];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type NearChunkTransaction = {
|
|
28
|
+
hash: string;
|
|
29
|
+
signer_id: string;
|
|
30
|
+
receiver_id: string;
|
|
31
|
+
actions: NearAction[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type NearAction = {
|
|
35
|
+
FunctionCall?: {
|
|
36
|
+
method_name: string;
|
|
37
|
+
args: string; // base64-encoded
|
|
38
|
+
gas: number;
|
|
39
|
+
deposit: string;
|
|
40
|
+
};
|
|
41
|
+
Transfer?: {
|
|
42
|
+
deposit: string;
|
|
43
|
+
};
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type NearChunk = {
|
|
48
|
+
header: {
|
|
49
|
+
chunk_hash: string;
|
|
50
|
+
shard_id: number;
|
|
51
|
+
height_included: number;
|
|
52
|
+
};
|
|
53
|
+
transactions: NearChunkTransaction[];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type NearExecutionOutcome = {
|
|
57
|
+
receipt_ids: string[];
|
|
58
|
+
status: { SuccessValue?: string; SuccessReceiptId?: string; Failure?: unknown };
|
|
59
|
+
logs: string[];
|
|
60
|
+
executor_id: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type NearExecutionOutcomeWithId = {
|
|
64
|
+
id: string;
|
|
65
|
+
outcome: NearExecutionOutcome;
|
|
66
|
+
block_hash: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type NearTxStatusResult = {
|
|
70
|
+
transaction: {
|
|
71
|
+
hash: string;
|
|
72
|
+
signer_id: string;
|
|
73
|
+
receiver_id: string;
|
|
74
|
+
actions: NearAction[];
|
|
75
|
+
};
|
|
76
|
+
transaction_outcome: NearExecutionOutcomeWithId;
|
|
77
|
+
receipts_outcome: NearExecutionOutcomeWithId[];
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// ==============
|
|
81
|
+
// NEP-297 events
|
|
82
|
+
// ==============
|
|
83
|
+
|
|
84
|
+
export type Nep297Event = {
|
|
85
|
+
standard: string;
|
|
86
|
+
version: string;
|
|
87
|
+
event: string;
|
|
88
|
+
data: unknown[];
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse a NEP-297 event from a NEAR execution log line.
|
|
93
|
+
* NEP-297 events have the format: `EVENT_JSON:{...}`
|
|
94
|
+
*/
|
|
95
|
+
export function parseNep297Log(log: string): Nep297Event | null {
|
|
96
|
+
if (!log.startsWith("EVENT_JSON:")) return null;
|
|
97
|
+
try {
|
|
98
|
+
return JSON.parse(log.slice("EVENT_JSON:".length));
|
|
99
|
+
} catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ===========
|
|
105
|
+
// RPC client
|
|
106
|
+
// ===========
|
|
107
|
+
|
|
108
|
+
export class NearClient {
|
|
109
|
+
private readonly rpcUrl: string;
|
|
110
|
+
|
|
111
|
+
constructor(rpcUrl: string) {
|
|
112
|
+
this.rpcUrl = rpcUrl;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private async rpc<T>(method: string, params: Record<string, unknown>): Promise<T> {
|
|
116
|
+
const res = await fetch(this.rpcUrl, {
|
|
117
|
+
method: "POST",
|
|
118
|
+
headers: { "Content-Type": "application/json" },
|
|
119
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const json = await res.json();
|
|
123
|
+
if (json.error) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`[NEAR] RPC error [${method}]: ${json.error.cause?.name ?? json.error.message ?? JSON.stringify(json.error)}`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return json.result as T;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async getBlock(
|
|
132
|
+
params: { finality: "final" | "optimistic" } | { block_id: number },
|
|
133
|
+
): Promise<NearBlock> {
|
|
134
|
+
return this.rpc<NearBlock>("block", params);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async getChunk(chunkHash: string): Promise<NearChunk> {
|
|
138
|
+
return this.rpc<NearChunk>("chunk", { chunk_id: chunkHash });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async getTxStatus(
|
|
142
|
+
txHash: string,
|
|
143
|
+
senderAccountId: string,
|
|
144
|
+
): Promise<NearTxStatusResult> {
|
|
145
|
+
return this.rpc<NearTxStatusResult>("EXPERIMENTAL_tx_status", {
|
|
146
|
+
tx_hash: txHash,
|
|
147
|
+
sender_account_id: senderAccountId,
|
|
148
|
+
wait_until: "EXECUTED",
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async getLatestBlockHeight(): Promise<number> {
|
|
153
|
+
const block = await this.getBlock({ finality: "final" });
|
|
154
|
+
return block.header.height;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async viewFunction(
|
|
158
|
+
accountId: string,
|
|
159
|
+
methodName: string,
|
|
160
|
+
argsBase64: string = "",
|
|
161
|
+
): Promise<unknown> {
|
|
162
|
+
const result = await this.rpc<{
|
|
163
|
+
result: number[];
|
|
164
|
+
logs: string[];
|
|
165
|
+
block_height: number;
|
|
166
|
+
block_hash: string;
|
|
167
|
+
}>("query", {
|
|
168
|
+
request_type: "call_function",
|
|
169
|
+
finality: "final",
|
|
170
|
+
account_id: accountId,
|
|
171
|
+
method_name: methodName,
|
|
172
|
+
args_base64: argsBase64,
|
|
173
|
+
});
|
|
174
|
+
const bytes = new Uint8Array(result.result);
|
|
175
|
+
const text = new TextDecoder().decode(bytes);
|
|
176
|
+
return JSON.parse(text);
|
|
177
|
+
}
|
|
178
|
+
}
|