@misofm/platform 0.0.0 → 0.18.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/LICENSE +201 -0
- package/README.md +686 -3
- package/dist/auth.d.ts +73 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +193 -0
- package/dist/auth.js.map +1 -0
- package/dist/catalog.d.ts +48 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +92 -0
- package/dist/catalog.js.map +1 -0
- package/dist/client.d.ts +462 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +788 -0
- package/dist/client.js.map +1 -0
- package/dist/contracts.d.ts +34 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +49 -0
- package/dist/contracts.js.map +1 -0
- package/dist/cover.d.ts +69 -0
- package/dist/cover.d.ts.map +1 -0
- package/dist/cover.js +132 -0
- package/dist/cover.js.map +1 -0
- package/dist/credits.d.ts +200 -0
- package/dist/credits.d.ts.map +1 -0
- package/dist/credits.js +465 -0
- package/dist/credits.js.map +1 -0
- package/dist/deployments.d.ts +224 -0
- package/dist/deployments.d.ts.map +1 -0
- package/dist/deployments.js +177 -0
- package/dist/deployments.js.map +1 -0
- package/dist/execute.d.ts +30 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +31 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +13 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +41 -0
- package/dist/internal.js.map +1 -0
- package/dist/mix.d.ts +144 -0
- package/dist/mix.d.ts.map +1 -0
- package/dist/mix.js +656 -0
- package/dist/mix.js.map +1 -0
- package/dist/pressing.d.ts +137 -0
- package/dist/pressing.d.ts.map +1 -0
- package/dist/pressing.js +390 -0
- package/dist/pressing.js.map +1 -0
- package/dist/publication.d.ts +216 -0
- package/dist/publication.d.ts.map +1 -0
- package/dist/publication.js +872 -0
- package/dist/publication.js.map +1 -0
- package/dist/queries.d.ts +2 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +8 -0
- package/dist/queries.js.map +1 -0
- package/dist/read/artist.d.ts +18 -0
- package/dist/read/artist.d.ts.map +1 -0
- package/dist/read/artist.js +86 -0
- package/dist/read/artist.js.map +1 -0
- package/dist/read/catalog.d.ts +93 -0
- package/dist/read/catalog.d.ts.map +1 -0
- package/dist/read/catalog.js +441 -0
- package/dist/read/catalog.js.map +1 -0
- package/dist/read/client.d.ts +37 -0
- package/dist/read/client.d.ts.map +1 -0
- package/dist/read/client.js +50 -0
- package/dist/read/client.js.map +1 -0
- package/dist/read/config.d.ts +68 -0
- package/dist/read/config.d.ts.map +1 -0
- package/dist/read/config.js +63 -0
- package/dist/read/config.js.map +1 -0
- package/dist/read/genres.d.ts +7 -0
- package/dist/read/genres.d.ts.map +1 -0
- package/dist/read/genres.js +38 -0
- package/dist/read/genres.js.map +1 -0
- package/dist/read/index.d.ts +14 -0
- package/dist/read/index.d.ts.map +1 -0
- package/dist/read/index.js +23 -0
- package/dist/read/index.js.map +1 -0
- package/dist/read/internal/scalars.d.ts +23 -0
- package/dist/read/internal/scalars.d.ts.map +1 -0
- package/dist/read/internal/scalars.js +57 -0
- package/dist/read/internal/scalars.js.map +1 -0
- package/dist/read/internal/walrus.d.ts +6 -0
- package/dist/read/internal/walrus.d.ts.map +1 -0
- package/dist/read/internal/walrus.js +29 -0
- package/dist/read/internal/walrus.js.map +1 -0
- package/dist/read/receipts.d.ts +41 -0
- package/dist/read/receipts.d.ts.map +1 -0
- package/dist/read/receipts.js +398 -0
- package/dist/read/receipts.js.map +1 -0
- package/dist/read/types.d.ts +328 -0
- package/dist/read/types.d.ts.map +1 -0
- package/dist/read/types.js +21 -0
- package/dist/read/types.js.map +1 -0
- package/dist/read/wallet.d.ts +74 -0
- package/dist/read/wallet.d.ts.map +1 -0
- package/dist/read/wallet.js +578 -0
- package/dist/read/wallet.js.map +1 -0
- package/dist/read/works.d.ts +29 -0
- package/dist/read/works.d.ts.map +1 -0
- package/dist/read/works.js +191 -0
- package/dist/read/works.js.map +1 -0
- package/dist/recording-extensions.d.ts +62 -0
- package/dist/recording-extensions.d.ts.map +1 -0
- package/dist/recording-extensions.js +159 -0
- package/dist/recording-extensions.js.map +1 -0
- package/dist/release-extensions.d.ts +93 -0
- package/dist/release-extensions.d.ts.map +1 -0
- package/dist/release-extensions.js +190 -0
- package/dist/release-extensions.js.map +1 -0
- package/dist/release-graph.d.ts +65 -0
- package/dist/release-graph.d.ts.map +1 -0
- package/dist/release-graph.js +136 -0
- package/dist/release-graph.js.map +1 -0
- package/dist/share-template.d.ts +3 -0
- package/dist/share-template.d.ts.map +1 -0
- package/dist/share-template.js +46 -0
- package/dist/share-template.js.map +1 -0
- package/dist/share.d.ts +67 -0
- package/dist/share.d.ts.map +1 -0
- package/dist/share.js +157 -0
- package/dist/share.js.map +1 -0
- package/dist/transactions.d.ts +216 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/transactions.js +314 -0
- package/dist/transactions.js.map +1 -0
- package/dist/vault.d.ts +364 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +507 -0
- package/dist/vault.js.map +1 -0
- package/package.json +145 -5
- package/src/auth.ts +275 -0
- package/src/catalog.ts +189 -0
- package/src/client.ts +1320 -0
- package/src/contracts.ts +54 -0
- package/src/cover.ts +240 -0
- package/src/credits.ts +906 -0
- package/src/deployments.ts +357 -0
- package/src/execute.ts +52 -0
- package/src/index.ts +69 -0
- package/src/internal.ts +46 -0
- package/src/mix.ts +910 -0
- package/src/pressing.ts +705 -0
- package/src/publication.ts +1214 -0
- package/src/queries.ts +9 -0
- package/src/read/artist.ts +118 -0
- package/src/read/catalog.ts +668 -0
- package/src/read/client.ts +87 -0
- package/src/read/config.ts +138 -0
- package/src/read/genres.ts +37 -0
- package/src/read/index.ts +85 -0
- package/src/read/internal/scalars.ts +59 -0
- package/src/read/internal/walrus.ts +42 -0
- package/src/read/receipts.ts +476 -0
- package/src/read/types.ts +415 -0
- package/src/read/wallet.ts +687 -0
- package/src/read/works.ts +297 -0
- package/src/recording-extensions.ts +256 -0
- package/src/release-extensions.ts +311 -0
- package/src/release-graph.ts +219 -0
- package/src/share-template.ts +55 -0
- package/src/share.ts +261 -0
- package/src/transactions.ts +542 -0
- package/src/vault.ts +1009 -0
package/src/share.ts
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// Copyright (c) Miso Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// Share-currency provisioning.
|
|
5
|
+
//
|
|
6
|
+
// Every composition and every recording is backed by its own fixed-supply
|
|
7
|
+
// (10M @ 6dp) share currency — an independently published `share` package whose
|
|
8
|
+
// `INITIALIZER` constant is patched to an authorized address before publish.
|
|
9
|
+
// Creating one is two transactions that CANNOT share a PTB: a `moveCall` target
|
|
10
|
+
// must name a concrete package id, but a package published in the same PTB has no
|
|
11
|
+
// id until it executes, so `${pkg}::share::initialize` must run in a later tx.
|
|
12
|
+
//
|
|
13
|
+
// The bytecode is identical for every currency (only the baked-in INITIALIZER
|
|
14
|
+
// matters, and it is the same signer for all), so publishes are fungible: a whole
|
|
15
|
+
// batch can be published — up to 5 `tx.publish` per PTB (the protocol's
|
|
16
|
+
// `max_publish_or_upgrade_per_ptb` cap) — and run concurrently through a
|
|
17
|
+
// `ParallelTransactionExecutor`. Every Publish result is consumed immediately by
|
|
18
|
+
// `package::make_immutable` in that same PTB, so no share-package UpgradeCap is
|
|
19
|
+
// ever left with the publisher. Initialization is likewise batched. The caller
|
|
20
|
+
// assigns packages to work slots and supplies per-package metadata, so each
|
|
21
|
+
// currency still gets a descriptive, work-specific name.
|
|
22
|
+
|
|
23
|
+
import type { ParallelTransactionExecutor } from "@mysten/sui/transactions";
|
|
24
|
+
import type { ClientWithCoreApi } from "@mysten/sui/client";
|
|
25
|
+
import type { Signer } from "@mysten/sui/cryptography";
|
|
26
|
+
import { fromBase64, fromHex, toBase64 } from "@mysten/sui/utils";
|
|
27
|
+
import { update_constants } from "@mysten/move-bytecode-template";
|
|
28
|
+
import {
|
|
29
|
+
execThunks,
|
|
30
|
+
publishedPackageId,
|
|
31
|
+
allPublishedPackageIds,
|
|
32
|
+
createdByType,
|
|
33
|
+
allCreatedByType,
|
|
34
|
+
type ExecResult,
|
|
35
|
+
} from "@misofm/protocol";
|
|
36
|
+
|
|
37
|
+
import { publishShareCurrency, initializeShareCurrency, type PackageBytecode } from "./transactions.ts";
|
|
38
|
+
import { SHARE_TEMPLATE } from "./share-template.ts";
|
|
39
|
+
import { executeViaExecutor } from "./execute.ts";
|
|
40
|
+
|
|
41
|
+
/** The protocol cap on Publish/Upgrade commands per programmable transaction. */
|
|
42
|
+
const PUBLISHES_PER_PTB = 5;
|
|
43
|
+
/** Initializes batched per PTB (each is one moveCall + transfer; all share the 0xc registry). */
|
|
44
|
+
const INITS_PER_PTB = 10;
|
|
45
|
+
|
|
46
|
+
// Address-free type markers: gRPC object types carry fully-normalized addresses
|
|
47
|
+
// (e.g. 0x0000…0002::coin::TreasuryCap), so we match on module::type rather than a
|
|
48
|
+
// short "0x2" prefix that would never match.
|
|
49
|
+
const CURRENCY_TYPE = "::coin_registry::Currency<";
|
|
50
|
+
const TREASURY_CAP_TYPE = "::coin::TreasuryCap<";
|
|
51
|
+
|
|
52
|
+
export interface ShareCurrency {
|
|
53
|
+
/** The published share package id. */
|
|
54
|
+
packageId: string;
|
|
55
|
+
/** The `Currency<Share>` object id. */
|
|
56
|
+
currencyId: string;
|
|
57
|
+
/** The fully-qualified share type, `${packageId}::share::Share`. */
|
|
58
|
+
shareType: string;
|
|
59
|
+
/** The `TreasuryCap<Share>` object id (held by the treasury-cap recipient). */
|
|
60
|
+
treasuryCapId: string;
|
|
61
|
+
/** Net gas (MIST) attributed to this currency, if tracked per-item (else 0). */
|
|
62
|
+
gasUsed: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ShareCurrencyMeta {
|
|
66
|
+
name: string;
|
|
67
|
+
description: string;
|
|
68
|
+
iconUrl?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── Bytecode patching ────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Patches the `INITIALIZER` constant in the share module bytecode, replacing the
|
|
75
|
+
* 32-byte zero-address placeholder with `initializerAddress`. The template is left
|
|
76
|
+
* untouched; a fresh patched copy is returned. `share::initialize` asserts the
|
|
77
|
+
* sender equals this address, so it must be the signer that will initialize.
|
|
78
|
+
*/
|
|
79
|
+
export function patchInitializer(template: PackageBytecode, initializerAddress: string): PackageBytecode {
|
|
80
|
+
const moduleBytes = fromBase64(template.modules[0]!);
|
|
81
|
+
|
|
82
|
+
// BCS-encoded vector<u8> of 32 zero bytes: [length=32, 0×32].
|
|
83
|
+
const oldValue = new Uint8Array(33);
|
|
84
|
+
oldValue[0] = 32;
|
|
85
|
+
|
|
86
|
+
// BCS-encoded vector<u8> of the initializer's 32 address bytes.
|
|
87
|
+
const newValue = new Uint8Array(33);
|
|
88
|
+
newValue[0] = 32;
|
|
89
|
+
newValue.set(fromHex(initializerAddress), 1);
|
|
90
|
+
|
|
91
|
+
const patched = update_constants(moduleBytes, newValue, oldValue, "Vector(U8)");
|
|
92
|
+
return { ...template, modules: [toBase64(patched)] };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ── Single (sequential) ──────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
export interface CreateShareCurrencyParams {
|
|
98
|
+
/** The share bytecode template. Defaults to the embedded {@link SHARE_TEMPLATE}. */
|
|
99
|
+
template?: PackageBytecode;
|
|
100
|
+
name: string;
|
|
101
|
+
description: string;
|
|
102
|
+
iconUrl?: string;
|
|
103
|
+
/** Address baked in as INITIALIZER; must be the signer. Defaults to the signer. */
|
|
104
|
+
initializerAddress?: string;
|
|
105
|
+
/** Recipient of the minted `TreasuryCap`. Defaults to the signer. */
|
|
106
|
+
treasuryCapRecipient?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Publishes an immutable package, then initializes a fresh share currency in a second tx. */
|
|
110
|
+
export async function createShareCurrency(
|
|
111
|
+
client: ClientWithCoreApi,
|
|
112
|
+
signer: Signer,
|
|
113
|
+
params: CreateShareCurrencyParams,
|
|
114
|
+
): Promise<ShareCurrency> {
|
|
115
|
+
const signerAddress = signer.toSuiAddress();
|
|
116
|
+
const initializer = params.initializerAddress ?? signerAddress;
|
|
117
|
+
const recipient = params.treasuryCapRecipient ?? signerAddress;
|
|
118
|
+
|
|
119
|
+
// Tx 1: publish the share package with the initializer baked in.
|
|
120
|
+
const patched = patchInitializer(params.template ?? SHARE_TEMPLATE, initializer);
|
|
121
|
+
const publishRes = await execThunks(client, signer, publishShareCurrency(patched));
|
|
122
|
+
const packageId = publishedPackageId(publishRes);
|
|
123
|
+
|
|
124
|
+
// Tx 2: initialize → creates the Currency object + transfers the TreasuryCap.
|
|
125
|
+
const initRes = await execThunks(
|
|
126
|
+
client,
|
|
127
|
+
signer,
|
|
128
|
+
initializeShareCurrency({
|
|
129
|
+
shareCurrencyPackageId: packageId,
|
|
130
|
+
name: params.name,
|
|
131
|
+
description: params.description,
|
|
132
|
+
iconUrl: params.iconUrl ?? "",
|
|
133
|
+
treasuryCapRecipient: recipient,
|
|
134
|
+
}),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
packageId,
|
|
139
|
+
currencyId: createdByType(initRes, CURRENCY_TYPE),
|
|
140
|
+
shareType: `${packageId}::share::Share`,
|
|
141
|
+
treasuryCapId: createdByType(initRes, TREASURY_CAP_TYPE),
|
|
142
|
+
gasUsed: publishRes.gasUsed + initRes.gasUsed,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ── Batched (parallel) ─────────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
/** Splits an array into fixed-size chunks. */
|
|
149
|
+
function chunk<T>(items: T[], size: number): T[][] {
|
|
150
|
+
const out: T[][] = [];
|
|
151
|
+
for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Publishes `count` fresh, permanently immutable share-currency packages, batched
|
|
157
|
+
* at ≤5 publishes per PTB and run concurrently through the executor. Each publish
|
|
158
|
+
* consumes its UpgradeCap in the same PTB. Returns the published package ids
|
|
159
|
+
* (fungible — order is not meaningful; the caller assigns them to work slots).
|
|
160
|
+
*/
|
|
161
|
+
export async function publishShareCurrencies(
|
|
162
|
+
executor: ParallelTransactionExecutor,
|
|
163
|
+
initializerAddress: string,
|
|
164
|
+
count: number,
|
|
165
|
+
template: PackageBytecode = SHARE_TEMPLATE,
|
|
166
|
+
): Promise<{ packageIds: string[]; gasUsed: number }> {
|
|
167
|
+
if (count <= 0) return { packageIds: [], gasUsed: 0 };
|
|
168
|
+
|
|
169
|
+
// One patched template, reused for every publish (identical bytecode → distinct packages).
|
|
170
|
+
const patched = patchInitializer(template, initializerAddress);
|
|
171
|
+
|
|
172
|
+
const batchSizes: number[] = [];
|
|
173
|
+
for (let remaining = count; remaining > 0; remaining -= PUBLISHES_PER_PTB) {
|
|
174
|
+
batchSizes.push(Math.min(PUBLISHES_PER_PTB, remaining));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const results = await Promise.all(
|
|
178
|
+
batchSizes.map((n) => executeViaExecutor(executor, ...Array.from({ length: n }, () => publishShareCurrency(patched)))),
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const packageIds = results.flatMap(allPublishedPackageIds);
|
|
182
|
+
const gasUsed = results.reduce((sum, r) => sum + r.gasUsed, 0);
|
|
183
|
+
if (packageIds.length !== count) {
|
|
184
|
+
throw new Error(`Expected ${count} published share packages, got ${packageIds.length}.`);
|
|
185
|
+
}
|
|
186
|
+
return { packageIds, gasUsed };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Re-associates one init PTB's created objects back to their packages by share type. */
|
|
190
|
+
function currenciesFromResult(res: ExecResult, batchPkgs: string[]): ShareCurrency[] {
|
|
191
|
+
const currencies = allCreatedByType(res, CURRENCY_TYPE);
|
|
192
|
+
const treasuries = allCreatedByType(res, TREASURY_CAP_TYPE);
|
|
193
|
+
return batchPkgs.map((pkg) => {
|
|
194
|
+
const shareType = `${pkg}::share::Share`;
|
|
195
|
+
const currency = currencies.find((o) => o.objectType.includes(shareType));
|
|
196
|
+
const treasury = treasuries.find((o) => o.objectType.includes(shareType));
|
|
197
|
+
if (!currency) throw new Error(`No Currency<${shareType}> created during initialize.`);
|
|
198
|
+
if (!treasury) throw new Error(`No TreasuryCap<${shareType}> created during initialize.`);
|
|
199
|
+
return { packageId: pkg, currencyId: currency.objectId, shareType, treasuryCapId: treasury.objectId, gasUsed: 0 };
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Initializes each published package into a `Currency<Share>` + `TreasuryCap`,
|
|
205
|
+
* batched and run concurrently. `metaOf` supplies each package's display metadata,
|
|
206
|
+
* so a currency destined for a specific work is named for it.
|
|
207
|
+
*
|
|
208
|
+
* `share::initialize` is NON-idempotent (`coin_registry` registers one `Currency`
|
|
209
|
+
* per type), so a batch must never be re-run. Batches run under `Promise.allSettled`
|
|
210
|
+
* and `onBatch` fires for each SUCCEEDED batch as it lands — letting the caller
|
|
211
|
+
* persist that batch immediately. If any batch fails, the succeeded ones are already
|
|
212
|
+
* reported and this throws, so a resume re-initializes only the still-missing packages.
|
|
213
|
+
*/
|
|
214
|
+
export async function initializeShareCurrencies(
|
|
215
|
+
executor: ParallelTransactionExecutor,
|
|
216
|
+
signerAddress: string,
|
|
217
|
+
packageIds: string[],
|
|
218
|
+
metaOf: (packageId: string) => ShareCurrencyMeta,
|
|
219
|
+
onBatch?: (currencies: ShareCurrency[], gasUsed: number) => void | Promise<void>,
|
|
220
|
+
): Promise<{ currencies: ShareCurrency[]; gasUsed: number }> {
|
|
221
|
+
if (packageIds.length === 0) return { currencies: [], gasUsed: 0 };
|
|
222
|
+
|
|
223
|
+
const batches = chunk(packageIds, INITS_PER_PTB);
|
|
224
|
+
const settled = await Promise.allSettled(
|
|
225
|
+
batches.map(async (batchPkgs) => {
|
|
226
|
+
const res = await executeViaExecutor(
|
|
227
|
+
executor,
|
|
228
|
+
...batchPkgs.map((pkg) => {
|
|
229
|
+
const meta = metaOf(pkg);
|
|
230
|
+
return initializeShareCurrency({
|
|
231
|
+
shareCurrencyPackageId: pkg,
|
|
232
|
+
name: meta.name,
|
|
233
|
+
description: meta.description,
|
|
234
|
+
iconUrl: meta.iconUrl ?? "",
|
|
235
|
+
treasuryCapRecipient: signerAddress,
|
|
236
|
+
});
|
|
237
|
+
}),
|
|
238
|
+
);
|
|
239
|
+
const batchCurrencies = currenciesFromResult(res, batchPkgs);
|
|
240
|
+
if (onBatch) await onBatch(batchCurrencies, res.gasUsed);
|
|
241
|
+
return { batchCurrencies, gasUsed: res.gasUsed };
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
const currencies: ShareCurrency[] = [];
|
|
246
|
+
const errors: unknown[] = [];
|
|
247
|
+
let gasUsed = 0;
|
|
248
|
+
for (const s of settled) {
|
|
249
|
+
if (s.status === "fulfilled") {
|
|
250
|
+
currencies.push(...s.value.batchCurrencies);
|
|
251
|
+
gasUsed += s.value.gasUsed;
|
|
252
|
+
} else {
|
|
253
|
+
errors.push(s.reason);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (errors.length > 0) {
|
|
257
|
+
const msg = errors.map((e) => (e instanceof Error ? e.message : String(e))).join("; ");
|
|
258
|
+
throw new Error(`${errors.length}/${batches.length} initialize batch(es) failed: ${msg}`);
|
|
259
|
+
}
|
|
260
|
+
return { currencies, gasUsed };
|
|
261
|
+
}
|