alkanesjs 1.2.0 → 1.2.2
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/index.browser.mjs +181 -11
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.d.ts +35 -1
- package/dist/index.js +179 -10
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -137,6 +137,25 @@ interface RpcCall<T> {
|
|
|
137
137
|
}
|
|
138
138
|
declare function buildRpcCall<T, E = unknown>(method: string, params: unknown[] | undefined, url: string): RpcCall<T>;
|
|
139
139
|
|
|
140
|
+
declare class WaitPacer {
|
|
141
|
+
private maxPerInterval;
|
|
142
|
+
private intervalMs;
|
|
143
|
+
private minGapMs;
|
|
144
|
+
private starts;
|
|
145
|
+
private lastStart;
|
|
146
|
+
private tail;
|
|
147
|
+
constructor(opts: {
|
|
148
|
+
maxPerInterval: number;
|
|
149
|
+
intervalMs: number;
|
|
150
|
+
});
|
|
151
|
+
setRate(maxPerInterval: number, intervalMs: number): void;
|
|
152
|
+
private now;
|
|
153
|
+
private sleep;
|
|
154
|
+
private pruneWindow;
|
|
155
|
+
/** Await this immediately before the call that could rate-limit */
|
|
156
|
+
waitForPacer(): Promise<void>;
|
|
157
|
+
}
|
|
158
|
+
|
|
140
159
|
interface ProviderConfig {
|
|
141
160
|
sandshrewUrl: string;
|
|
142
161
|
electrumApiUrl: string;
|
|
@@ -144,10 +163,15 @@ interface ProviderConfig {
|
|
|
144
163
|
explorerUrl: string;
|
|
145
164
|
defaultFeeRate?: number;
|
|
146
165
|
btcTicker?: string;
|
|
166
|
+
pacerSettings?: PacerSettings;
|
|
147
167
|
}
|
|
148
168
|
declare enum AlkanesPollError {
|
|
149
169
|
UnknownError = "UnknownError"
|
|
150
170
|
}
|
|
171
|
+
type PacerSettings = {
|
|
172
|
+
intervalMs: number;
|
|
173
|
+
maxPerInterval: number;
|
|
174
|
+
};
|
|
151
175
|
type AlkanesParsedTraceResult = {
|
|
152
176
|
create?: AlkanesTraceCreateEvent["data"];
|
|
153
177
|
invoke?: AlkanesTraceInvokeEvent["data"];
|
|
@@ -158,11 +182,14 @@ declare class Provider {
|
|
|
158
182
|
readonly electrumApiUrl: string;
|
|
159
183
|
readonly network: Network;
|
|
160
184
|
readonly explorerUrl: string;
|
|
185
|
+
readonly pacerSettings: PacerSettings;
|
|
161
186
|
readonly btcTicker: string;
|
|
187
|
+
readonly jitterMs = 1000;
|
|
162
188
|
readonly rpc: BaseRpcProvider;
|
|
163
189
|
readonly defaultFeeRate: number;
|
|
164
190
|
private readonly TIMEOUT_MS;
|
|
165
191
|
private readonly INTERVAL_MS;
|
|
192
|
+
pacer: WaitPacer;
|
|
166
193
|
constructor(config: ProviderConfig);
|
|
167
194
|
protected txUrl(txid: string): string;
|
|
168
195
|
protected addressUrl(address: string): string;
|
|
@@ -186,6 +213,9 @@ declare class ElectrumApiProvider {
|
|
|
186
213
|
esplora_broadcastTx(rawTransactionHex: string, customElectrumUrl?: string): Promise<BoxedResponse<string, EsploraFetchError>>;
|
|
187
214
|
esplora_getaddresstxs(address: string, lastSeenTransactionId?: string): Promise<BoxedResponse<IEsploraTransaction[], EsploraFetchError>>;
|
|
188
215
|
esplora_getbulktransactions(transactionIds: string[]): Promise<BoxedResponse<IEsploraTransaction[], EsploraFetchError>>;
|
|
216
|
+
esplora_getblocktiphash(): Promise<BoxedResponse<string, EsploraFetchError>>;
|
|
217
|
+
_esplora_getrawblock(blockHash: string): Promise<BoxedResponse<string, EsploraFetchError>>;
|
|
218
|
+
esplora_getrawblocktip(): Promise<BoxedResponse<string, EsploraFetchError>>;
|
|
189
219
|
esplora_gettransaction(transactionId: string): Promise<BoxedResponse<IEsploraTransaction, EsploraFetchError>>;
|
|
190
220
|
esplora_getrawtransaction(transactionId: string): Promise<BoxedResponse<string, EsploraFetchError>>;
|
|
191
221
|
esplora_getspendableinputs(utxoList: EsploraUtxo[]): Promise<BoxedResponse<IEsploraSpendableUtxo[], EsploraFetchError>>;
|
|
@@ -585,6 +615,10 @@ declare class BaseRpcProvider {
|
|
|
585
615
|
}
|
|
586
616
|
|
|
587
617
|
declare const stripHex: (s: string) => string;
|
|
618
|
+
declare function toU64LittleEndianHex(numStr: string): string;
|
|
619
|
+
declare function makeFakeBlock(height: number | bigint): string;
|
|
620
|
+
declare function toU64BigEndianHex(numStr: string): string;
|
|
621
|
+
declare function toU128LittleEndianHex(numStr: string): string;
|
|
588
622
|
declare function mapToPrimitives(v: any): any;
|
|
589
623
|
declare function unmapFromPrimitives(v: any): any;
|
|
590
624
|
declare function parseSimulateReturn(v: string): AlkanesParsedSimulationResult | undefined;
|
|
@@ -1478,5 +1512,5 @@ declare const TokenContract_base: new (provider: Provider, alkaneId: AlkaneId, s
|
|
|
1478
1512
|
declare class TokenContract extends TokenContract_base {
|
|
1479
1513
|
}
|
|
1480
1514
|
|
|
1481
|
-
export { AddressType, AlkanesBaseContract, AlkanesExecuteError, AlkanesFetchError, AlkanesInscription, AlkanesRpcProvider, AlkanesSimulationError, AlkanesTraceError, BaseRpcProvider, DecodableAlkanesResponse, DecodeError, EcPair, ElectrumApiProvider, Encodable, EncodeError, EsploraFetchError, OrdFetchError, OrdRpcProvider, ParsableAlkaneId, ProtostoneTransaction, ProtostoneTransactionWithInscription, Provider, RpcError, RunesFetchError, RunesRpcProvider, SandshrewFetchError, SandshrewRpcProvider, TokenABI, TokenContract, abi, addInputDynamic, addressFormats, addressNameToType, addressTypeToName, assertHex, buildRpcCall, calculateTaprootTxSize, decodeAlkanesTrace, decodeCBOR, excludeFields, execute, extractAbiErrorMessage, extractWithDummySigs, formatInputsToSign, getAddressType, getDummyProtostoneTransaction, getEstimatedFee, getProtostoneTransactionsWithInscription, getProtostoneUnsignedPsbtBase64, getVSize, hexToUint8Array, mapToPrimitives, minimumFee, parseSimulateReturn, psbtBuilder, redeemTypeFromOutput, reverseHexBytes, schemaAlkaneId, simulate, sleep, stripHex, tapTweakHash, toEsploraTx, toFormattedUtxo, trimUndefined, tweakSigner, u128Schema, unmapFromPrimitives, witnessStackToScriptWitness };
|
|
1515
|
+
export { AddressType, AlkanesBaseContract, AlkanesExecuteError, AlkanesFetchError, AlkanesInscription, AlkanesRpcProvider, AlkanesSimulationError, AlkanesTraceError, BaseRpcProvider, DecodableAlkanesResponse, DecodeError, EcPair, ElectrumApiProvider, Encodable, EncodeError, EsploraFetchError, OrdFetchError, OrdRpcProvider, ParsableAlkaneId, ProtostoneTransaction, ProtostoneTransactionWithInscription, Provider, RpcError, RunesFetchError, RunesRpcProvider, SandshrewFetchError, SandshrewRpcProvider, TokenABI, TokenContract, abi, addInputDynamic, addressFormats, addressNameToType, addressTypeToName, assertHex, buildRpcCall, calculateTaprootTxSize, decodeAlkanesTrace, decodeCBOR, excludeFields, execute, extractAbiErrorMessage, extractWithDummySigs, formatInputsToSign, getAddressType, getDummyProtostoneTransaction, getEstimatedFee, getProtostoneTransactionsWithInscription, getProtostoneUnsignedPsbtBase64, getVSize, hexToUint8Array, makeFakeBlock, mapToPrimitives, minimumFee, parseSimulateReturn, psbtBuilder, redeemTypeFromOutput, reverseHexBytes, schemaAlkaneId, simulate, sleep, stripHex, tapTweakHash, toEsploraTx, toFormattedUtxo, toU128LittleEndianHex, toU64BigEndianHex, toU64LittleEndianHex, trimUndefined, tweakSigner, u128Schema, unmapFromPrimitives, witnessStackToScriptWitness };
|
|
1482
1516
|
export type { Account, AddressKey, Alkane, AlkaneDetails, AlkaneEncoded, AlkaneEncodedSimulationRequest, AlkaneId, AlkaneReadableId, AlkaneRune, AlkaneSimulateRequest, AlkaneToken, AlkanesByAddressOutpoint, AlkanesByAddressResponse, AlkanesByAddressRuneBalance, AlkanesExecuteResponse, AlkanesOutpoint, AlkanesOutpointExtended, AlkanesOutpoints, AlkanesOutpointsExtended, AlkanesParsedSimulationResult, AlkanesParsedTraceResult, AlkanesPushExecuteResponse, AlkanesRawSimulationResponse, AlkanesSimulationResult, AlkanesTraceCreateEvent, AlkanesTraceEncodedCreateEvent, AlkanesTraceEncodedEvent, AlkanesTraceEncodedInvokeEvent, AlkanesTraceEncodedResult, AlkanesTraceEncodedReturnEvent, AlkanesTraceEvent, AlkanesTraceInvokeEvent, AlkanesTraceResult, AlkanesTraceReturnEvent, AlkanesUtxo, AlkanesUtxoBalance, AlkanesUtxoEntry, AvailableDecodeKind, AvailableEncodeKind, CustomSpec, Dec, DecodedCBOR, DecodedCBORValue, DecoderFns, Enc, EncodedAlkaneId, EncoderFns, EsploraAddressResponse, EsploraAddressStats, EsploraUtxo, ExecuteSpec, Expand, FormattedUtxo, HDPaths, IDecodableAlkanesResponse, IEncodable, IEsploraBlockHeader, IEsploraPrevout, IEsploraSpendableUtxo, IEsploraTransaction, IEsploraTransactionStatus, IEsploraVin, IEsploraVout, ISchemaAlkaneId, OpcodeTable, OrdBlock, OrdInscription, OrdOutput, OrdOutputRune, OrdPaginatedIds, OrdSat, ProtoRunesToken, ProtostoneTransactionOptions, ProtostoneTransactionOptionsPartial, ProviderConfig, PsbtInputExtended, ResolveSchema, RpcCall, RpcResponse, RpcTuple, Rune, RuneBalance, RuneName, RunesAddressResult, RunesOutpoint, RunesOutpointResult, Schema, SingularAlkanesTransfer, SingularBTCTransfer, SingularTransfer, SpendStrategy, ViewSpec, WalletStandard };
|
package/dist/index.js
CHANGED
|
@@ -34791,6 +34791,7 @@ __export(src_exports, {
|
|
|
34791
34791
|
getProtostoneUnsignedPsbtBase64: () => getProtostoneUnsignedPsbtBase64,
|
|
34792
34792
|
getVSize: () => getVSize,
|
|
34793
34793
|
hexToUint8Array: () => hexToUint8Array,
|
|
34794
|
+
makeFakeBlock: () => makeFakeBlock,
|
|
34794
34795
|
mapToPrimitives: () => mapToPrimitives,
|
|
34795
34796
|
minimumFee: () => minimumFee,
|
|
34796
34797
|
parseSimulateReturn: () => parseSimulateReturn,
|
|
@@ -34804,6 +34805,9 @@ __export(src_exports, {
|
|
|
34804
34805
|
tapTweakHash: () => tapTweakHash,
|
|
34805
34806
|
toEsploraTx: () => toEsploraTx,
|
|
34806
34807
|
toFormattedUtxo: () => toFormattedUtxo,
|
|
34808
|
+
toU128LittleEndianHex: () => toU128LittleEndianHex,
|
|
34809
|
+
toU64BigEndianHex: () => toU64BigEndianHex,
|
|
34810
|
+
toU64LittleEndianHex: () => toU64LittleEndianHex,
|
|
34807
34811
|
trimUndefined: () => trimUndefined,
|
|
34808
34812
|
tweakSigner: () => tweakSigner,
|
|
34809
34813
|
u128Schema: () => u128Schema,
|
|
@@ -37299,7 +37303,8 @@ var ProtostoneTransaction = class {
|
|
|
37299
37303
|
this.fee = Math.max(baseFee, this.MINIMUM_FEE);
|
|
37300
37304
|
}
|
|
37301
37305
|
calcCumulativeSpendRequirements() {
|
|
37302
|
-
this.cumulativeSpendRequirementBtc = this.fee + this.MINIMUM_PROTOCOL_DUST *
|
|
37306
|
+
this.cumulativeSpendRequirementBtc = this.fee + this.MINIMUM_PROTOCOL_DUST * (this.transactionOptions.transfers?.length ?? 0) + this.MINIMUM_PROTOCOL_DUST;
|
|
37307
|
+
console.log(this.cumulativeSpendRequirementBtc);
|
|
37303
37308
|
this.cumulativeSpendRequirementAlkanes = this.transactionOptions.transfers.reduce(
|
|
37304
37309
|
(acc, transfer) => {
|
|
37305
37310
|
if (isBTCTransfer(transfer)) {
|
|
@@ -37527,7 +37532,7 @@ var ProtostoneTransaction = class {
|
|
|
37527
37532
|
),
|
|
37528
37533
|
// Convert bigint to string for JSON compatibility
|
|
37529
37534
|
amount: (0, import_integer.u128)(transfer.amount),
|
|
37530
|
-
output: (0, import_integer.u32)(outputIds[address3] +
|
|
37535
|
+
output: (0, import_integer.u32)(outputIds[address3] + 1)
|
|
37531
37536
|
};
|
|
37532
37537
|
if (!alkanesEdicts[address3]) {
|
|
37533
37538
|
alkanesEdicts[address3] = {};
|
|
@@ -37547,6 +37552,7 @@ var ProtostoneTransaction = class {
|
|
|
37547
37552
|
output: edict.output
|
|
37548
37553
|
}))
|
|
37549
37554
|
);
|
|
37555
|
+
console.log(transactionEdicts[0]);
|
|
37550
37556
|
return transactionEdicts;
|
|
37551
37557
|
}
|
|
37552
37558
|
addProtostoneData(edicts) {
|
|
@@ -42513,6 +42519,53 @@ var ElectrumApiProvider = class {
|
|
|
42513
42519
|
);
|
|
42514
42520
|
}
|
|
42515
42521
|
}
|
|
42522
|
+
async esplora_getblocktiphash() {
|
|
42523
|
+
try {
|
|
42524
|
+
const requestUrl = `${this.electrumApiUrl}/blocks/tip/hash`;
|
|
42525
|
+
const httpResponse = await fetch(requestUrl);
|
|
42526
|
+
if (!httpResponse.ok) {
|
|
42527
|
+
return new BoxedError(
|
|
42528
|
+
"UnknownError" /* UnknownError */,
|
|
42529
|
+
`Failed to fetch tip hash from ${requestUrl}: ${httpResponse.statusText}`
|
|
42530
|
+
);
|
|
42531
|
+
}
|
|
42532
|
+
const tipHash = (await httpResponse.text()).trim();
|
|
42533
|
+
return new BoxedSuccess(tipHash);
|
|
42534
|
+
} catch (error) {
|
|
42535
|
+
return new BoxedError(
|
|
42536
|
+
"UnknownError" /* UnknownError */,
|
|
42537
|
+
`Failed to fetch tip hash: ${error.message}`
|
|
42538
|
+
);
|
|
42539
|
+
}
|
|
42540
|
+
}
|
|
42541
|
+
async _esplora_getrawblock(blockHash) {
|
|
42542
|
+
try {
|
|
42543
|
+
const requestUrl = `${this.electrumApiUrl}/block/${blockHash}/raw`;
|
|
42544
|
+
const httpResponse = await fetch(requestUrl);
|
|
42545
|
+
if (!httpResponse.ok) {
|
|
42546
|
+
return new BoxedError(
|
|
42547
|
+
"UnknownError" /* UnknownError */,
|
|
42548
|
+
`Failed to fetch raw block ${blockHash} from ${requestUrl}: ${httpResponse.statusText}`
|
|
42549
|
+
);
|
|
42550
|
+
}
|
|
42551
|
+
const bytes = new Uint8Array(await httpResponse.arrayBuffer());
|
|
42552
|
+
const rawHex = Array.from(
|
|
42553
|
+
bytes,
|
|
42554
|
+
(b) => b.toString(16).padStart(2, "0")
|
|
42555
|
+
).join("");
|
|
42556
|
+
return new BoxedSuccess("0x" + rawHex);
|
|
42557
|
+
} catch (error) {
|
|
42558
|
+
return new BoxedError(
|
|
42559
|
+
"UnknownError" /* UnknownError */,
|
|
42560
|
+
`Failed to fetch raw block ${blockHash}: ${error.message}`
|
|
42561
|
+
);
|
|
42562
|
+
}
|
|
42563
|
+
}
|
|
42564
|
+
async esplora_getrawblocktip() {
|
|
42565
|
+
const tipHashResponse = await this.esplora_getblocktiphash();
|
|
42566
|
+
if (isBoxedError(tipHashResponse)) return tipHashResponse;
|
|
42567
|
+
return this._esplora_getrawblock(tipHashResponse.data);
|
|
42568
|
+
}
|
|
42516
42569
|
/*
|
|
42517
42570
|
async esplora_getbulktransactions(
|
|
42518
42571
|
transactionIds: string[],
|
|
@@ -45066,6 +45119,42 @@ var OrdRpcProvider = class {
|
|
|
45066
45119
|
|
|
45067
45120
|
// src/apis/alkanes/utils.ts
|
|
45068
45121
|
var stripHex = (s) => s.startsWith("0x") ? s.slice(2) : s;
|
|
45122
|
+
function toU64LittleEndianHex(numStr) {
|
|
45123
|
+
const num = BigInt(numStr);
|
|
45124
|
+
const hex = num.toString(16).padStart(16, "0");
|
|
45125
|
+
const bytes = hex.match(/.{2}/g);
|
|
45126
|
+
if (!bytes) throw new Error("Invalid hex conversion");
|
|
45127
|
+
const littleEndian = bytes.reverse().join("");
|
|
45128
|
+
return `0x${littleEndian}`;
|
|
45129
|
+
}
|
|
45130
|
+
function makeFakeBlock(height) {
|
|
45131
|
+
const buf = new Uint8Array(80);
|
|
45132
|
+
const h = BigInt(height);
|
|
45133
|
+
for (let i = 0; i < 8; i++) {
|
|
45134
|
+
buf[72 + i] = Number(h >> BigInt(8 * i) & 0xffn);
|
|
45135
|
+
}
|
|
45136
|
+
const hex = Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
45137
|
+
return `${hex}`;
|
|
45138
|
+
}
|
|
45139
|
+
function toU64BigEndianHex(numStr) {
|
|
45140
|
+
const MAX_U64 = BigInt("0xffffffffffffffff");
|
|
45141
|
+
const num = BigInt(numStr);
|
|
45142
|
+
if (num < 0n || num > MAX_U64) {
|
|
45143
|
+
throw new RangeError("Value exceeds u64 range");
|
|
45144
|
+
}
|
|
45145
|
+
const hex = num.toString(16).padStart(16, "0");
|
|
45146
|
+
return `0x${hex}`;
|
|
45147
|
+
}
|
|
45148
|
+
function toU128LittleEndianHex(numStr) {
|
|
45149
|
+
const MAX_U1282 = BigInt("0xffffffffffffffffffffffffffffffff");
|
|
45150
|
+
const num = BigInt(numStr);
|
|
45151
|
+
if (num < 0n || num > MAX_U1282) {
|
|
45152
|
+
throw new RangeError("Value exceeds u128 range");
|
|
45153
|
+
}
|
|
45154
|
+
const hex = num.toString(16).padStart(32, "0");
|
|
45155
|
+
const littleEndian = hex.match(/.{2}/g).reverse().join("");
|
|
45156
|
+
return `0x${littleEndian}`;
|
|
45157
|
+
}
|
|
45069
45158
|
function mapToPrimitives(v) {
|
|
45070
45159
|
switch (typeof v) {
|
|
45071
45160
|
case "bigint":
|
|
@@ -45074,7 +45163,9 @@ function mapToPrimitives(v) {
|
|
|
45074
45163
|
if (v === null) return null;
|
|
45075
45164
|
if (Buffer.isBuffer(v)) return "0x" + v.toString("hex");
|
|
45076
45165
|
if (Array.isArray(v)) return v.map(mapToPrimitives);
|
|
45077
|
-
return Object.fromEntries(
|
|
45166
|
+
return Object.fromEntries(
|
|
45167
|
+
Object.entries(v).map(([k, val]) => [k, mapToPrimitives(val)])
|
|
45168
|
+
);
|
|
45078
45169
|
}
|
|
45079
45170
|
default:
|
|
45080
45171
|
return v;
|
|
@@ -45083,13 +45174,16 @@ function mapToPrimitives(v) {
|
|
|
45083
45174
|
function unmapFromPrimitives(v) {
|
|
45084
45175
|
switch (typeof v) {
|
|
45085
45176
|
case "string":
|
|
45086
|
-
if (v.startsWith("0x") && v !== "0x")
|
|
45177
|
+
if (v.startsWith("0x") && v !== "0x")
|
|
45178
|
+
return Buffer.from(stripHex(v), "hex");
|
|
45087
45179
|
if (!isNaN(v)) return BigInt(v);
|
|
45088
45180
|
return v;
|
|
45089
45181
|
case "object": {
|
|
45090
45182
|
if (v === null) return null;
|
|
45091
45183
|
if (Array.isArray(v)) return v.map(unmapFromPrimitives);
|
|
45092
|
-
return Object.fromEntries(
|
|
45184
|
+
return Object.fromEntries(
|
|
45185
|
+
Object.entries(v).map(([k, val]) => [k, unmapFromPrimitives(val)])
|
|
45186
|
+
);
|
|
45093
45187
|
}
|
|
45094
45188
|
default:
|
|
45095
45189
|
return v;
|
|
@@ -45099,7 +45193,9 @@ function parseSimulateReturn(v) {
|
|
|
45099
45193
|
if (v === "0x") return void 0;
|
|
45100
45194
|
const toUtf8 = Buffer.from(stripHex(v), "hex").toString("utf8");
|
|
45101
45195
|
const isUtf8 = !/[\uFFFD]/.test(toUtf8);
|
|
45102
|
-
const rev = Buffer.from(
|
|
45196
|
+
const rev = Buffer.from(
|
|
45197
|
+
Array.from(Buffer.from(stripHex(v), "hex")).reverse()
|
|
45198
|
+
).toString("hex");
|
|
45103
45199
|
return {
|
|
45104
45200
|
string: isUtf8 ? toUtf8 : "0x" + stripHex(v),
|
|
45105
45201
|
bytes: "0x" + stripHex(v),
|
|
@@ -45216,6 +45312,7 @@ var AlkanesRpcProvider = class {
|
|
|
45216
45312
|
payload: ["alkanes_trace", [{ txid: leTxid, vout }]],
|
|
45217
45313
|
call: async () => {
|
|
45218
45314
|
try {
|
|
45315
|
+
await this.provider.pacer.waitForPacer();
|
|
45219
45316
|
const encoded = consumeOrThrow(
|
|
45220
45317
|
await this.rpc("alkanes_trace", [
|
|
45221
45318
|
{ txid: leTxid, vout }
|
|
@@ -45287,14 +45384,12 @@ var AlkanesRpcProvider = class {
|
|
|
45287
45384
|
]);
|
|
45288
45385
|
}
|
|
45289
45386
|
async alkanes_simulate(req) {
|
|
45290
|
-
|
|
45291
|
-
await this.alkanes_metashrewHeight().call()
|
|
45292
|
-
);
|
|
45387
|
+
await this.provider.pacer.waitForPacer();
|
|
45293
45388
|
const merged = {
|
|
45294
45389
|
alkanes: req.alkanes ?? [],
|
|
45295
45390
|
transaction: req.transaction ?? "0x",
|
|
45296
45391
|
block: "0x",
|
|
45297
|
-
height:
|
|
45392
|
+
height: "908474",
|
|
45298
45393
|
txindex: req.txindex ?? 0,
|
|
45299
45394
|
target: {
|
|
45300
45395
|
block: req.target?.block?.toString() ?? "0",
|
|
@@ -45305,6 +45400,7 @@ var AlkanesRpcProvider = class {
|
|
|
45305
45400
|
refundPointer: req.refundPointer ?? 0,
|
|
45306
45401
|
vout: req.vout ?? 0
|
|
45307
45402
|
};
|
|
45403
|
+
console.log(merged);
|
|
45308
45404
|
const res = await this.rpc(
|
|
45309
45405
|
"alkanes_simulate",
|
|
45310
45406
|
[merged]
|
|
@@ -45647,27 +45743,96 @@ var schemaAlkaneId = import_borsher4.BorshSchema.Struct({
|
|
|
45647
45743
|
tx: import_borsher4.BorshSchema.u64
|
|
45648
45744
|
});
|
|
45649
45745
|
|
|
45746
|
+
// src/pacer.ts
|
|
45747
|
+
var WaitPacer = class {
|
|
45748
|
+
maxPerInterval;
|
|
45749
|
+
intervalMs;
|
|
45750
|
+
minGapMs;
|
|
45751
|
+
// track start times within the sliding window
|
|
45752
|
+
starts = [];
|
|
45753
|
+
lastStart = 0;
|
|
45754
|
+
// serialize callers so their start times are paced correctly
|
|
45755
|
+
tail = Promise.resolve();
|
|
45756
|
+
constructor(opts) {
|
|
45757
|
+
this.maxPerInterval = Math.max(1, opts.maxPerInterval);
|
|
45758
|
+
this.intervalMs = Math.max(1, opts.intervalMs);
|
|
45759
|
+
this.minGapMs = Math.floor(this.intervalMs / this.maxPerInterval);
|
|
45760
|
+
}
|
|
45761
|
+
setRate(maxPerInterval, intervalMs) {
|
|
45762
|
+
this.maxPerInterval = Math.max(1, maxPerInterval);
|
|
45763
|
+
this.intervalMs = Math.max(1, intervalMs);
|
|
45764
|
+
this.minGapMs = Math.floor(this.intervalMs / this.maxPerInterval);
|
|
45765
|
+
}
|
|
45766
|
+
now() {
|
|
45767
|
+
return Date.now();
|
|
45768
|
+
}
|
|
45769
|
+
sleep(ms) {
|
|
45770
|
+
return ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
|
|
45771
|
+
}
|
|
45772
|
+
pruneWindow(now) {
|
|
45773
|
+
const cutoff = now - this.intervalMs;
|
|
45774
|
+
while (this.starts.length && this.starts[0] <= cutoff) this.starts.shift();
|
|
45775
|
+
}
|
|
45776
|
+
/** Await this immediately before the call that could rate-limit */
|
|
45777
|
+
waitForPacer() {
|
|
45778
|
+
const ticket = this.tail.then(async () => {
|
|
45779
|
+
while (true) {
|
|
45780
|
+
const now = this.now();
|
|
45781
|
+
this.pruneWindow(now);
|
|
45782
|
+
if (this.starts.length >= this.maxPerInterval) {
|
|
45783
|
+
const earliest = this.starts[0];
|
|
45784
|
+
const waitUntil = earliest + this.intervalMs;
|
|
45785
|
+
await this.sleep(Math.max(0, waitUntil - this.now()));
|
|
45786
|
+
continue;
|
|
45787
|
+
}
|
|
45788
|
+
const earliestStart = this.lastStart + this.minGapMs;
|
|
45789
|
+
const delay = Math.max(0, earliestStart - now);
|
|
45790
|
+
if (delay > 0) {
|
|
45791
|
+
await this.sleep(delay);
|
|
45792
|
+
continue;
|
|
45793
|
+
}
|
|
45794
|
+
const startTs = this.now();
|
|
45795
|
+
this.lastStart = startTs;
|
|
45796
|
+
this.starts.push(startTs);
|
|
45797
|
+
break;
|
|
45798
|
+
}
|
|
45799
|
+
});
|
|
45800
|
+
this.tail = ticket.catch(() => {
|
|
45801
|
+
});
|
|
45802
|
+
return ticket;
|
|
45803
|
+
}
|
|
45804
|
+
};
|
|
45805
|
+
|
|
45650
45806
|
// src/provider.ts
|
|
45651
45807
|
var Provider = class {
|
|
45652
45808
|
sandshrewUrl;
|
|
45653
45809
|
electrumApiUrl;
|
|
45654
45810
|
network;
|
|
45655
45811
|
explorerUrl;
|
|
45812
|
+
pacerSettings = {
|
|
45813
|
+
intervalMs: 1e3,
|
|
45814
|
+
maxPerInterval: 10
|
|
45815
|
+
};
|
|
45656
45816
|
btcTicker;
|
|
45817
|
+
jitterMs = 1e3;
|
|
45818
|
+
// 1 second
|
|
45657
45819
|
rpc;
|
|
45658
45820
|
defaultFeeRate;
|
|
45659
45821
|
TIMEOUT_MS = 6e4 * 5;
|
|
45660
45822
|
// 5 minutes
|
|
45661
45823
|
INTERVAL_MS = 5e3;
|
|
45662
45824
|
// 5 seconds
|
|
45825
|
+
pacer;
|
|
45663
45826
|
constructor(config) {
|
|
45664
45827
|
this.sandshrewUrl = config.sandshrewUrl;
|
|
45665
45828
|
this.electrumApiUrl = config.electrumApiUrl;
|
|
45666
45829
|
this.network = config.network;
|
|
45667
45830
|
this.explorerUrl = config.explorerUrl.replace(/\/+$/, "");
|
|
45668
45831
|
this.btcTicker = config.btcTicker ?? "BTC";
|
|
45832
|
+
this.pacerSettings = config.pacerSettings ?? this.pacerSettings;
|
|
45669
45833
|
this.defaultFeeRate = config.defaultFeeRate ?? 5;
|
|
45670
45834
|
this.rpc = new BaseRpcProvider(this);
|
|
45835
|
+
this.pacer = new WaitPacer(this.pacerSettings);
|
|
45671
45836
|
}
|
|
45672
45837
|
txUrl(txid) {
|
|
45673
45838
|
return `${this.explorerUrl}/tx/${txid}`;
|
|
@@ -45863,6 +46028,7 @@ bitcoin2.initEccLib(ecc);
|
|
|
45863
46028
|
getProtostoneUnsignedPsbtBase64,
|
|
45864
46029
|
getVSize,
|
|
45865
46030
|
hexToUint8Array,
|
|
46031
|
+
makeFakeBlock,
|
|
45866
46032
|
mapToPrimitives,
|
|
45867
46033
|
minimumFee,
|
|
45868
46034
|
parseSimulateReturn,
|
|
@@ -45876,6 +46042,9 @@ bitcoin2.initEccLib(ecc);
|
|
|
45876
46042
|
tapTweakHash,
|
|
45877
46043
|
toEsploraTx,
|
|
45878
46044
|
toFormattedUtxo,
|
|
46045
|
+
toU128LittleEndianHex,
|
|
46046
|
+
toU64BigEndianHex,
|
|
46047
|
+
toU64LittleEndianHex,
|
|
45879
46048
|
trimUndefined,
|
|
45880
46049
|
tweakSigner,
|
|
45881
46050
|
u128Schema,
|