@arkade-os/sdk 0.4.0-next.2 → 0.4.0-next.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/cjs/{asset → extension/asset}/index.js +1 -2
- package/dist/cjs/extension/asset/packet.js +111 -0
- package/dist/cjs/{asset → extension/asset}/types.js +1 -4
- package/dist/cjs/extension/index.js +254 -0
- package/dist/cjs/extension/packet.js +20 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/providers/ark.js +52 -37
- package/dist/cjs/providers/indexer.js +1 -1
- package/dist/cjs/providers/utils.js +39 -29
- package/dist/cjs/wallet/asset-manager.js +9 -17
- package/dist/cjs/wallet/asset.js +1 -1
- package/dist/cjs/wallet/validation.js +6 -2
- package/dist/cjs/wallet/wallet.js +5 -4
- package/dist/cjs/worker/browser/service-worker-manager.js +111 -10
- package/dist/esm/{asset → extension/asset}/index.js +1 -1
- package/dist/esm/extension/asset/packet.js +107 -0
- package/dist/esm/{asset → extension/asset}/types.js +0 -3
- package/dist/esm/extension/index.js +248 -0
- package/dist/esm/extension/packet.js +16 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/providers/ark.js +52 -37
- package/dist/esm/providers/indexer.js +1 -1
- package/dist/esm/providers/utils.js +39 -29
- package/dist/esm/wallet/asset-manager.js +9 -17
- package/dist/esm/wallet/asset.js +1 -1
- package/dist/esm/wallet/validation.js +6 -2
- package/dist/esm/wallet/wallet.js +5 -4
- package/dist/esm/worker/browser/service-worker-manager.js +111 -10
- package/dist/types/{asset → extension/asset}/index.d.ts +1 -1
- package/dist/types/extension/asset/packet.d.ts +38 -0
- package/dist/types/{asset → extension/asset}/types.d.ts +0 -2
- package/dist/types/extension/index.d.ts +56 -0
- package/dist/types/extension/packet.d.ts +21 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/providers/utils.d.ts +6 -0
- package/dist/types/wallet/asset-manager.d.ts +4 -13
- package/dist/types/wallet/asset.d.ts +1 -1
- package/dist/types/worker/browser/service-worker-manager.d.ts +15 -4
- package/package.json +1 -1
- package/dist/cjs/asset/packet.js +0 -164
- package/dist/esm/asset/packet.js +0 -159
- package/dist/types/asset/packet.d.ts +0 -27
- /package/dist/cjs/{asset → extension/asset}/assetGroup.js +0 -0
- /package/dist/cjs/{asset → extension/asset}/assetId.js +0 -0
- /package/dist/cjs/{asset → extension/asset}/assetInput.js +0 -0
- /package/dist/cjs/{asset → extension/asset}/assetOutput.js +0 -0
- /package/dist/cjs/{asset → extension/asset}/assetRef.js +0 -0
- /package/dist/cjs/{asset → extension/asset}/metadata.js +0 -0
- /package/dist/cjs/{asset → extension/asset}/utils.js +0 -0
- /package/dist/esm/{asset → extension/asset}/assetGroup.js +0 -0
- /package/dist/esm/{asset → extension/asset}/assetId.js +0 -0
- /package/dist/esm/{asset → extension/asset}/assetInput.js +0 -0
- /package/dist/esm/{asset → extension/asset}/assetOutput.js +0 -0
- /package/dist/esm/{asset → extension/asset}/assetRef.js +0 -0
- /package/dist/esm/{asset → extension/asset}/metadata.js +0 -0
- /package/dist/esm/{asset → extension/asset}/utils.js +0 -0
- /package/dist/types/{asset → extension/asset}/assetGroup.d.ts +0 -0
- /package/dist/types/{asset → extension/asset}/assetId.d.ts +0 -0
- /package/dist/types/{asset → extension/asset}/assetInput.d.ts +0 -0
- /package/dist/types/{asset → extension/asset}/assetOutput.d.ts +0 -0
- /package/dist/types/{asset → extension/asset}/assetRef.d.ts +0 -0
- /package/dist/types/{asset → extension/asset}/metadata.d.ts +0 -0
- /package/dist/types/{asset → extension/asset}/utils.d.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Packet = exports.AssetGroup = exports.MetadataList = exports.Metadata = exports.AssetOutputs = exports.AssetOutput = exports.AssetInputs = exports.AssetInput = exports.AssetRef = exports.AssetId = exports.AssetRefType = exports.AssetInputType = void 0;
|
|
4
4
|
var types_1 = require("./types");
|
|
5
5
|
Object.defineProperty(exports, "AssetInputType", { enumerable: true, get: function () { return types_1.AssetInputType; } });
|
|
6
6
|
Object.defineProperty(exports, "AssetRefType", { enumerable: true, get: function () { return types_1.AssetRefType; } });
|
|
@@ -21,4 +21,3 @@ var assetGroup_1 = require("./assetGroup");
|
|
|
21
21
|
Object.defineProperty(exports, "AssetGroup", { enumerable: true, get: function () { return assetGroup_1.AssetGroup; } });
|
|
22
22
|
var packet_1 = require("./packet");
|
|
23
23
|
Object.defineProperty(exports, "Packet", { enumerable: true, get: function () { return packet_1.Packet; } });
|
|
24
|
-
Object.defineProperty(exports, "AssetPacketNotFoundError", { enumerable: true, get: function () { return packet_1.AssetPacketNotFoundError; } });
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Packet = void 0;
|
|
4
|
+
const base_1 = require("@scure/base");
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
const assetGroup_1 = require("./assetGroup");
|
|
7
|
+
const utils_1 = require("./utils");
|
|
8
|
+
/**
|
|
9
|
+
* Packet represents a collection of asset groups.
|
|
10
|
+
* It encodes/decodes as raw bytes only — OP_RETURN framing is handled by the Extension module.
|
|
11
|
+
*/
|
|
12
|
+
class Packet {
|
|
13
|
+
constructor(groups) {
|
|
14
|
+
this.groups = groups;
|
|
15
|
+
}
|
|
16
|
+
static create(groups) {
|
|
17
|
+
const p = new Packet(groups);
|
|
18
|
+
p.validate();
|
|
19
|
+
return p;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* fromBytes parses a Packet from raw bytes.
|
|
23
|
+
*/
|
|
24
|
+
static fromBytes(buf) {
|
|
25
|
+
return Packet.fromReader(new utils_1.BufferReader(buf));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* fromString parses a Packet from a raw hex string (not an OP_RETURN script).
|
|
29
|
+
*/
|
|
30
|
+
static fromString(s) {
|
|
31
|
+
if (!s) {
|
|
32
|
+
throw new Error("missing packet data");
|
|
33
|
+
}
|
|
34
|
+
let buf;
|
|
35
|
+
try {
|
|
36
|
+
buf = base_1.hex.decode(s);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new Error("invalid packet format, must be hex");
|
|
40
|
+
}
|
|
41
|
+
return Packet.fromBytes(buf);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* type returns the TLV packet type tag. Implements ExtensionPacket interface.
|
|
45
|
+
*/
|
|
46
|
+
type() {
|
|
47
|
+
return Packet.PACKET_TYPE;
|
|
48
|
+
}
|
|
49
|
+
leafTxPacket(intentTxid) {
|
|
50
|
+
const leafGroups = this.groups.map((group) => group.toBatchLeafAssetGroup(intentTxid));
|
|
51
|
+
return new Packet(leafGroups);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* serialize encodes the packet as raw bytes (varint group count + group data).
|
|
55
|
+
* Does NOT include OP_RETURN, ARK magic, or TLV type/length — those are
|
|
56
|
+
* added by the Extension module.
|
|
57
|
+
*/
|
|
58
|
+
serialize() {
|
|
59
|
+
if (this.groups.length === 0) {
|
|
60
|
+
return new Uint8Array(0);
|
|
61
|
+
}
|
|
62
|
+
const writer = new utils_1.BufferWriter();
|
|
63
|
+
writer.writeVarUint(this.groups.length);
|
|
64
|
+
for (const group of this.groups) {
|
|
65
|
+
group.serializeTo(writer);
|
|
66
|
+
}
|
|
67
|
+
return writer.toBytes();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* toString returns the hex-encoded raw packet bytes.
|
|
71
|
+
*/
|
|
72
|
+
toString() {
|
|
73
|
+
return base_1.hex.encode(this.serialize());
|
|
74
|
+
}
|
|
75
|
+
validate() {
|
|
76
|
+
if (this.groups.length === 0) {
|
|
77
|
+
throw new Error("missing assets");
|
|
78
|
+
}
|
|
79
|
+
const seenAssetIds = new Set();
|
|
80
|
+
for (const group of this.groups) {
|
|
81
|
+
if (group.assetId !== null) {
|
|
82
|
+
const key = group.assetId.toString();
|
|
83
|
+
if (seenAssetIds.has(key)) {
|
|
84
|
+
throw new Error(`duplicate asset group for asset ${key}`);
|
|
85
|
+
}
|
|
86
|
+
seenAssetIds.add(key);
|
|
87
|
+
}
|
|
88
|
+
if (group.controlAsset !== null &&
|
|
89
|
+
group.controlAsset.ref.type === types_1.AssetRefType.ByGroup &&
|
|
90
|
+
group.controlAsset.ref.groupIndex >= this.groups.length) {
|
|
91
|
+
throw new Error(`invalid control asset group index, ${group.controlAsset.ref.groupIndex} out of range [0, ${this.groups.length - 1}]`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
static fromReader(reader) {
|
|
96
|
+
const count = Number(reader.readVarUint());
|
|
97
|
+
const groups = [];
|
|
98
|
+
for (let i = 0; i < count; i++) {
|
|
99
|
+
groups.push(assetGroup_1.AssetGroup.fromReader(reader));
|
|
100
|
+
}
|
|
101
|
+
if (reader.remaining() > 0) {
|
|
102
|
+
throw new Error(`invalid packet length, left ${reader.remaining()} unknown bytes to read`);
|
|
103
|
+
}
|
|
104
|
+
const packet = new Packet(groups);
|
|
105
|
+
packet.validate();
|
|
106
|
+
return packet;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.Packet = Packet;
|
|
110
|
+
/** PACKET_TYPE is the 1-byte TLV type tag used in the Extension envelope. */
|
|
111
|
+
Packet.PACKET_TYPE = 0;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.MASK_METADATA = exports.MASK_CONTROL_ASSET = exports.MASK_ASSET_ID = exports.AssetRefType = exports.AssetInputType = exports.ASSET_VERSION = exports.ASSET_ID_SIZE = exports.TX_HASH_SIZE = void 0;
|
|
4
4
|
exports.TX_HASH_SIZE = 32;
|
|
5
5
|
exports.ASSET_ID_SIZE = 34;
|
|
6
6
|
exports.ASSET_VERSION = 0x01;
|
|
@@ -20,6 +20,3 @@ var AssetRefType;
|
|
|
20
20
|
exports.MASK_ASSET_ID = 0x01;
|
|
21
21
|
exports.MASK_CONTROL_ASSET = 0x02;
|
|
22
22
|
exports.MASK_METADATA = 0x04;
|
|
23
|
-
// ARK magic bytes and marker
|
|
24
|
-
exports.ARKADE_MAGIC = new Uint8Array([0x41, 0x52, 0x4b]); // "ARK"
|
|
25
|
-
exports.MARKER_ASSET_PAYLOAD = 0x00;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Extension = exports.ExtensionNotFoundError = exports.ARKADE_MAGIC = exports.UnknownPacket = void 0;
|
|
4
|
+
const base_1 = require("@scure/base");
|
|
5
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
6
|
+
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
7
|
+
const packet_1 = require("./asset/packet");
|
|
8
|
+
const utils_1 = require("./asset/utils");
|
|
9
|
+
const packet_2 = require("./packet");
|
|
10
|
+
var packet_3 = require("./packet");
|
|
11
|
+
Object.defineProperty(exports, "UnknownPacket", { enumerable: true, get: function () { return packet_3.UnknownPacket; } });
|
|
12
|
+
/**
|
|
13
|
+
* ArkadeMagic is the 3-byte magic prefix ("ARK") that identifies an OP_RETURN
|
|
14
|
+
* output as an ark extension blob.
|
|
15
|
+
*/
|
|
16
|
+
exports.ARKADE_MAGIC = new Uint8Array([0x41, 0x52, 0x4b]); // "ARK"
|
|
17
|
+
/**
|
|
18
|
+
* ErrExtensionNotFound is thrown when no extension output is found in a transaction.
|
|
19
|
+
*/
|
|
20
|
+
class ExtensionNotFoundError extends Error {
|
|
21
|
+
constructor() {
|
|
22
|
+
super("no extension output found in transaction");
|
|
23
|
+
this.name = "ExtensionNotFoundError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.ExtensionNotFoundError = ExtensionNotFoundError;
|
|
27
|
+
/**
|
|
28
|
+
* Extension is a set of typed packets encoded in an OP_RETURN output.
|
|
29
|
+
*
|
|
30
|
+
* Wire format:
|
|
31
|
+
* OP_RETURN | <push> | ARK(3B) | [type(1B) | varint_len | data]...
|
|
32
|
+
*/
|
|
33
|
+
class Extension {
|
|
34
|
+
constructor(packets) {
|
|
35
|
+
this.packets = packets;
|
|
36
|
+
}
|
|
37
|
+
static create(packets) {
|
|
38
|
+
if (packets.length === 0) {
|
|
39
|
+
throw new Error("missing packets");
|
|
40
|
+
}
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
for (const p of packets) {
|
|
43
|
+
if (seen.has(p.type())) {
|
|
44
|
+
throw new Error(`duplicate packet type ${p.type()}`);
|
|
45
|
+
}
|
|
46
|
+
seen.add(p.type());
|
|
47
|
+
}
|
|
48
|
+
return new Extension(packets);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* isExtension returns true if the script is an OP_RETURN whose push data
|
|
52
|
+
* begins with the ARK magic bytes.
|
|
53
|
+
*/
|
|
54
|
+
static isExtension(script) {
|
|
55
|
+
try {
|
|
56
|
+
const decoded = btc_signer_1.Script.decode(script);
|
|
57
|
+
if (decoded.length < 2 || decoded[0] !== "RETURN")
|
|
58
|
+
return false;
|
|
59
|
+
const data = decoded[1];
|
|
60
|
+
if (!(data instanceof Uint8Array))
|
|
61
|
+
return false;
|
|
62
|
+
return (data.length >= exports.ARKADE_MAGIC.length &&
|
|
63
|
+
(0, utils_js_1.equalBytes)(data.slice(0, exports.ARKADE_MAGIC.length), exports.ARKADE_MAGIC));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* fromBytes parses an Extension from a raw OP_RETURN script.
|
|
71
|
+
*/
|
|
72
|
+
static fromBytes(script) {
|
|
73
|
+
if (!script || script.length === 0) {
|
|
74
|
+
throw new Error("missing OP_RETURN");
|
|
75
|
+
}
|
|
76
|
+
let decoded;
|
|
77
|
+
try {
|
|
78
|
+
decoded = btc_signer_1.Script.decode(script);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
throw new Error("expected OP_RETURN");
|
|
82
|
+
}
|
|
83
|
+
if (decoded.length === 0 || decoded[0] !== "RETURN") {
|
|
84
|
+
throw new Error("expected OP_RETURN");
|
|
85
|
+
}
|
|
86
|
+
const dataPushes = decoded
|
|
87
|
+
.slice(1)
|
|
88
|
+
.filter((x) => x instanceof Uint8Array);
|
|
89
|
+
if (dataPushes.length === 0) {
|
|
90
|
+
throw new Error("missing magic prefix: EOF");
|
|
91
|
+
}
|
|
92
|
+
// Concatenate all data pushes (handles OP_PUSHDATA1/2/4)
|
|
93
|
+
const payload = new Uint8Array(dataPushes.reduce((acc, d) => acc + d.length, 0));
|
|
94
|
+
let offset = 0;
|
|
95
|
+
for (const d of dataPushes) {
|
|
96
|
+
payload.set(d, offset);
|
|
97
|
+
offset += d.length;
|
|
98
|
+
}
|
|
99
|
+
// Check ARK magic
|
|
100
|
+
if (payload.length < exports.ARKADE_MAGIC.length ||
|
|
101
|
+
!(0, utils_js_1.equalBytes)(payload.slice(0, exports.ARKADE_MAGIC.length), exports.ARKADE_MAGIC)) {
|
|
102
|
+
throw new Error(`expected magic prefix ${base_1.hex.encode(exports.ARKADE_MAGIC)}, got ${base_1.hex.encode(payload.slice(0, Math.min(payload.length, exports.ARKADE_MAGIC.length)))}`);
|
|
103
|
+
}
|
|
104
|
+
// Parse TLV records
|
|
105
|
+
const reader = new utils_1.BufferReader(payload.slice(exports.ARKADE_MAGIC.length));
|
|
106
|
+
const packets = [];
|
|
107
|
+
while (reader.remaining() > 0) {
|
|
108
|
+
const packetType = reader.readByte();
|
|
109
|
+
let data;
|
|
110
|
+
try {
|
|
111
|
+
data = reader.readVarSlice();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
throw new Error("missing packet data");
|
|
115
|
+
}
|
|
116
|
+
packets.push(parsePacket(packetType, data));
|
|
117
|
+
}
|
|
118
|
+
if (packets.length === 0) {
|
|
119
|
+
throw new Error("missing packets");
|
|
120
|
+
}
|
|
121
|
+
// Reject duplicate packet types
|
|
122
|
+
const seen = new Set();
|
|
123
|
+
for (const p of packets) {
|
|
124
|
+
if (seen.has(p.type())) {
|
|
125
|
+
throw new Error(`duplicate packet type ${p.type()}`);
|
|
126
|
+
}
|
|
127
|
+
seen.add(p.type());
|
|
128
|
+
}
|
|
129
|
+
return new Extension(packets);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* fromTx searches the transaction outputs for an extension blob and parses it.
|
|
133
|
+
* Throws ExtensionNotFoundError if none is found.
|
|
134
|
+
*/
|
|
135
|
+
static fromTx(tx) {
|
|
136
|
+
for (let i = 0; i < tx.outputsLength; i++) {
|
|
137
|
+
const output = tx.getOutput(i);
|
|
138
|
+
if (!output?.script)
|
|
139
|
+
continue;
|
|
140
|
+
if (Extension.isExtension(output.script)) {
|
|
141
|
+
return Extension.fromBytes(output.script);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
throw new ExtensionNotFoundError();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* serialize encodes the extension as an OP_RETURN script.
|
|
148
|
+
*
|
|
149
|
+
* Layout: OP_RETURN | <push> | ARK | [type | varint_len | data]...
|
|
150
|
+
*/
|
|
151
|
+
serialize() {
|
|
152
|
+
// Build payload: ARK magic + TLV records
|
|
153
|
+
const parts = [exports.ARKADE_MAGIC];
|
|
154
|
+
for (const p of this.packets) {
|
|
155
|
+
const data = p.serialize();
|
|
156
|
+
// type (1 byte)
|
|
157
|
+
const typeByte = new Uint8Array([p.type()]);
|
|
158
|
+
// varint length prefix + data
|
|
159
|
+
const lengthBuf = encodeVarUint(data.length);
|
|
160
|
+
parts.push(typeByte, lengthBuf, data);
|
|
161
|
+
}
|
|
162
|
+
const totalLen = parts.reduce((acc, p) => acc + p.length, 0);
|
|
163
|
+
const payload = new Uint8Array(totalLen);
|
|
164
|
+
let off = 0;
|
|
165
|
+
for (const p of parts) {
|
|
166
|
+
payload.set(p, off);
|
|
167
|
+
off += p.length;
|
|
168
|
+
}
|
|
169
|
+
return buildOpReturnScript(payload);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* txOut returns the extension as a zero-value OP_RETURN transaction output.
|
|
173
|
+
*/
|
|
174
|
+
txOut() {
|
|
175
|
+
return {
|
|
176
|
+
script: this.serialize(),
|
|
177
|
+
amount: 0n,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* getAssetPacket returns the embedded Packet, or null if not present.
|
|
182
|
+
*/
|
|
183
|
+
getAssetPacket() {
|
|
184
|
+
for (const p of this.packets) {
|
|
185
|
+
if (p instanceof packet_1.Packet) {
|
|
186
|
+
return p;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.Extension = Extension;
|
|
193
|
+
/**
|
|
194
|
+
* parsePacket dispatches to a known packet type or falls back to UnknownPacket.
|
|
195
|
+
*/
|
|
196
|
+
function parsePacket(packetType, data) {
|
|
197
|
+
if (packetType === packet_1.Packet.PACKET_TYPE) {
|
|
198
|
+
return packet_1.Packet.fromBytes(data);
|
|
199
|
+
}
|
|
200
|
+
return new packet_2.UnknownPacket(packetType, data);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* encodeVarUint encodes a non-negative integer as a LEB128 unsigned varint.
|
|
204
|
+
*/
|
|
205
|
+
function encodeVarUint(value) {
|
|
206
|
+
const bytes = [];
|
|
207
|
+
let remaining = value;
|
|
208
|
+
do {
|
|
209
|
+
let byte = remaining & 0x7f;
|
|
210
|
+
remaining >>>= 7;
|
|
211
|
+
if (remaining > 0)
|
|
212
|
+
byte |= 0x80;
|
|
213
|
+
bytes.push(byte);
|
|
214
|
+
} while (remaining > 0);
|
|
215
|
+
return new Uint8Array(bytes);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* buildOpReturnScript builds an OP_RETURN script with an arbitrary-length data push.
|
|
219
|
+
* Manually constructed to avoid the 520-byte cap in some script builders.
|
|
220
|
+
*
|
|
221
|
+
* Opcodes: 0x6a=OP_RETURN, 0x4c=OP_PUSHDATA1, 0x4d=OP_PUSHDATA2, 0x4e=OP_PUSHDATA4
|
|
222
|
+
*/
|
|
223
|
+
function buildOpReturnScript(data) {
|
|
224
|
+
const n = data.length;
|
|
225
|
+
let script;
|
|
226
|
+
if (n <= 75) {
|
|
227
|
+
script = new Uint8Array(2 + n);
|
|
228
|
+
script[0] = 0x6a; // OP_RETURN
|
|
229
|
+
script[1] = n;
|
|
230
|
+
script.set(data, 2);
|
|
231
|
+
}
|
|
232
|
+
else if (n <= 255) {
|
|
233
|
+
script = new Uint8Array(3 + n);
|
|
234
|
+
script[0] = 0x6a;
|
|
235
|
+
script[1] = 0x4c; // OP_PUSHDATA1
|
|
236
|
+
script[2] = n;
|
|
237
|
+
script.set(data, 3);
|
|
238
|
+
}
|
|
239
|
+
else if (n <= 65535) {
|
|
240
|
+
script = new Uint8Array(4 + n);
|
|
241
|
+
script[0] = 0x6a;
|
|
242
|
+
script[1] = 0x4d; // OP_PUSHDATA2
|
|
243
|
+
new DataView(script.buffer).setUint16(2, n, true);
|
|
244
|
+
script.set(data, 4);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
script = new Uint8Array(6 + n);
|
|
248
|
+
script[0] = 0x6a;
|
|
249
|
+
script[1] = 0x4e; // OP_PUSHDATA4
|
|
250
|
+
new DataView(script.buffer).setUint32(2, n, true);
|
|
251
|
+
script.set(data, 6);
|
|
252
|
+
}
|
|
253
|
+
return script;
|
|
254
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnknownPacket = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* UnknownPacket holds a packet whose type is not recognized by this implementation.
|
|
6
|
+
* It round-trips opaquely: the raw bytes are preserved as-is.
|
|
7
|
+
*/
|
|
8
|
+
class UnknownPacket {
|
|
9
|
+
constructor(packetType, data) {
|
|
10
|
+
this.packetType = packetType;
|
|
11
|
+
this.data = data;
|
|
12
|
+
}
|
|
13
|
+
type() {
|
|
14
|
+
return this.packetType;
|
|
15
|
+
}
|
|
16
|
+
serialize() {
|
|
17
|
+
return this.data;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.UnknownPacket = UnknownPacket;
|
package/dist/cjs/index.js
CHANGED
|
@@ -156,7 +156,7 @@ Object.defineProperty(exports, "ContractRepositoryImpl", { enumerable: true, get
|
|
|
156
156
|
const delegator_2 = require("./wallet/delegator");
|
|
157
157
|
Object.defineProperty(exports, "DelegatorManagerImpl", { enumerable: true, get: function () { return delegator_2.DelegatorManagerImpl; } });
|
|
158
158
|
__exportStar(require("./arkfee"), exports);
|
|
159
|
-
exports.asset = __importStar(require("./asset"));
|
|
159
|
+
exports.asset = __importStar(require("./extension/asset"));
|
|
160
160
|
// Contracts
|
|
161
161
|
const contracts_1 = require("./contracts");
|
|
162
162
|
Object.defineProperty(exports, "ContractManager", { enumerable: true, get: function () { return contracts_1.ContractManager; } });
|
|
@@ -225,54 +225,69 @@ class RestArkProvider {
|
|
|
225
225
|
handleError(errorText, `Failed to submit forfeit transactions: ${response.statusText}`);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
-
|
|
228
|
+
getEventStream(signal, topics) {
|
|
229
229
|
const url = `${this.serverUrl}/v1/batch/events`;
|
|
230
230
|
const queryParams = topics.length > 0
|
|
231
231
|
? `?${topics.map((topic) => `topics=${encodeURIComponent(topic)}`).join("&")}`
|
|
232
232
|
: "";
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
// Create first EventSource eagerly so events are buffered
|
|
234
|
+
// before the caller starts iterating, preventing race conditions
|
|
235
|
+
// where the server emits events before iteration begins.
|
|
236
|
+
const eagerEventSource = new EventSource(url + queryParams);
|
|
237
|
+
const eagerIterator = (0, utils_1.eventSourceIterator)(eagerEventSource);
|
|
238
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
239
|
+
const self = this;
|
|
240
|
+
return (async function* () {
|
|
241
|
+
let firstIteration = true;
|
|
242
|
+
while (!signal?.aborted) {
|
|
243
|
+
const eventSource = firstIteration
|
|
244
|
+
? eagerEventSource
|
|
245
|
+
: new EventSource(url + queryParams);
|
|
246
|
+
const iterator = firstIteration
|
|
247
|
+
? eagerIterator
|
|
248
|
+
: (0, utils_1.eventSourceIterator)(eventSource);
|
|
249
|
+
firstIteration = false;
|
|
241
250
|
try {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (
|
|
249
|
-
|
|
251
|
+
const abortHandler = () => {
|
|
252
|
+
eventSource.close();
|
|
253
|
+
};
|
|
254
|
+
signal?.addEventListener("abort", abortHandler);
|
|
255
|
+
try {
|
|
256
|
+
for await (const event of iterator) {
|
|
257
|
+
if (signal?.aborted)
|
|
258
|
+
break;
|
|
259
|
+
try {
|
|
260
|
+
const data = JSON.parse(event.data);
|
|
261
|
+
const settlementEvent = self.parseSettlementEvent(data);
|
|
262
|
+
if (settlementEvent) {
|
|
263
|
+
yield settlementEvent;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
console.error("Failed to parse event:", err);
|
|
268
|
+
throw err;
|
|
250
269
|
}
|
|
251
|
-
}
|
|
252
|
-
catch (err) {
|
|
253
|
-
console.error("Failed to parse event:", err);
|
|
254
|
-
throw err;
|
|
255
270
|
}
|
|
256
271
|
}
|
|
272
|
+
finally {
|
|
273
|
+
signal?.removeEventListener("abort", abortHandler);
|
|
274
|
+
eventSource.close();
|
|
275
|
+
}
|
|
257
276
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
console.debug("Timeout error ignored");
|
|
270
|
-
continue;
|
|
277
|
+
catch (error) {
|
|
278
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
// ignore timeout errors, they're expected when the server is not sending anything for 5 min
|
|
282
|
+
if (isFetchTimeoutError(error)) {
|
|
283
|
+
console.debug("Timeout error ignored");
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
console.error("Event stream error:", error);
|
|
287
|
+
throw error;
|
|
271
288
|
}
|
|
272
|
-
console.error("Event stream error:", error);
|
|
273
|
-
throw error;
|
|
274
289
|
}
|
|
275
|
-
}
|
|
290
|
+
})();
|
|
276
291
|
}
|
|
277
292
|
async *getTransactionsStream(signal) {
|
|
278
293
|
const url = `${this.serverUrl}/v1/txs`;
|
|
@@ -4,7 +4,7 @@ exports.RestIndexerProvider = exports.ChainTxType = exports.IndexerTxType = void
|
|
|
4
4
|
const base_1 = require("@scure/base");
|
|
5
5
|
const ark_1 = require("./ark");
|
|
6
6
|
const utils_1 = require("./utils");
|
|
7
|
-
const asset_1 = require("../asset");
|
|
7
|
+
const asset_1 = require("../extension/asset");
|
|
8
8
|
var IndexerTxType;
|
|
9
9
|
(function (IndexerTxType) {
|
|
10
10
|
IndexerTxType[IndexerTxType["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.eventSourceIterator = eventSourceIterator;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Creates an async iterator over EventSource messages that attaches listeners
|
|
6
|
+
* eagerly (at call time) rather than lazily (at first .next() call).
|
|
7
|
+
* This ensures events are buffered immediately, preventing race conditions
|
|
8
|
+
* where events arrive before iteration begins.
|
|
9
|
+
*/
|
|
10
|
+
function eventSourceIterator(eventSource) {
|
|
5
11
|
const messageQueue = [];
|
|
6
12
|
const errorQueue = [];
|
|
7
13
|
let messageResolve = null;
|
|
@@ -26,36 +32,40 @@ async function* eventSourceIterator(eventSource) {
|
|
|
26
32
|
errorQueue.push(error);
|
|
27
33
|
}
|
|
28
34
|
};
|
|
35
|
+
// Attach listeners immediately so events are buffered
|
|
36
|
+
// even before the caller starts iterating
|
|
29
37
|
eventSource.addEventListener("message", messageHandler);
|
|
30
38
|
eventSource.addEventListener("error", errorHandler);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
39
|
+
return (async function* () {
|
|
40
|
+
try {
|
|
41
|
+
while (true) {
|
|
42
|
+
// if we have queued messages, yield the first one, remove it from the queue
|
|
43
|
+
if (messageQueue.length > 0) {
|
|
44
|
+
yield messageQueue.shift();
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// if we have queued errors, throw the first one, remove it from the queue
|
|
48
|
+
if (errorQueue.length > 0) {
|
|
49
|
+
const error = errorQueue.shift();
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
// wait for the next message or error
|
|
53
|
+
const result = await new Promise((resolve, reject) => {
|
|
54
|
+
messageResolve = resolve;
|
|
55
|
+
errorResolve = reject;
|
|
56
|
+
}).finally(() => {
|
|
57
|
+
messageResolve = null;
|
|
58
|
+
errorResolve = null;
|
|
59
|
+
});
|
|
60
|
+
if (result) {
|
|
61
|
+
yield result;
|
|
62
|
+
}
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
65
|
+
finally {
|
|
66
|
+
// clean up
|
|
67
|
+
eventSource.removeEventListener("message", messageHandler);
|
|
68
|
+
eventSource.removeEventListener("error", errorHandler);
|
|
69
|
+
}
|
|
70
|
+
})();
|
|
61
71
|
}
|