@bigmaxwatermelon/sdk 0.4.4 → 0.4.6

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/cli.js CHANGED
@@ -26,7 +26,7 @@ var init_env = __esm({
26
26
 
27
27
  // src/sdk/rpc/wallet.ts
28
28
  import { ethers } from "ethers";
29
- function createWallet2(rpcUrl, privateKey) {
29
+ function createWallet(rpcUrl, privateKey) {
30
30
  if (privateKey) return new PrivateKeyWallet(rpcUrl, privateKey);
31
31
  return new ReadOnlyWallet(rpcUrl);
32
32
  }
@@ -3736,7 +3736,7 @@ var init_StableCoinBeacon = __esm({
3736
3736
  // src/sdk/rpc/contracts.ts
3737
3737
  var contracts_exports = {};
3738
3738
  __export(contracts_exports, {
3739
- getContracts: () => getContracts2,
3739
+ getContracts: () => getContracts,
3740
3740
  getPlatform: () => getPlatform,
3741
3741
  getStableCoin: () => getStableCoin
3742
3742
  });
@@ -3744,7 +3744,7 @@ import { Contract } from "ethers";
3744
3744
  function abiOf(artifact) {
3745
3745
  return artifact.abi;
3746
3746
  }
3747
- function getContracts2(addresses, runner) {
3747
+ function getContracts(addresses, runner) {
3748
3748
  if (!addresses.platform) throw new Error("ISOMETRY_PLATFORM_ADDRESS is required");
3749
3749
  if (!addresses.factory) throw new Error("ISOMETRY_FACTORY_ADDRESS is required");
3750
3750
  if (!addresses.beacon) throw new Error("ISOMETRY_BEACON_ADDRESS is required");
@@ -3781,7 +3781,7 @@ var init_platform = __esm({
3781
3781
  contracts;
3782
3782
  platform;
3783
3783
  constructor(addresses, runner) {
3784
- this.contracts = getContracts2(addresses, runner);
3784
+ this.contracts = getContracts(addresses, runner);
3785
3785
  this.platform = this.contracts.platform;
3786
3786
  }
3787
3787
  async getPlatformInfo() {
@@ -3840,11 +3840,11 @@ var init_factory = __esm({
3840
3840
  this.runner = runner;
3841
3841
  }
3842
3842
  async getBeaconAddress() {
3843
- const { factory } = getContracts2(this.addresses, this.runner);
3843
+ const { factory } = getContracts(this.addresses, this.runner);
3844
3844
  return factory.beacon();
3845
3845
  }
3846
3846
  async getPlatformAddress() {
3847
- const { factory } = getContracts2(this.addresses, this.runner);
3847
+ const { factory } = getContracts(this.addresses, this.runner);
3848
3848
  return factory.platform();
3849
3849
  }
3850
3850
  };
@@ -3930,17 +3930,275 @@ var init_stablecoin = __esm({
3930
3930
  });
3931
3931
 
3932
3932
  // src/sdk/rpc/errorMap.ts
3933
+ function decodeError(details) {
3934
+ if (details.data && details.data !== "0x") {
3935
+ const selector = details.data.slice(0, 10).toLowerCase();
3936
+ const mapped = ERROR_SELECTOR_MAP[selector];
3937
+ if (mapped) return mapped;
3938
+ }
3939
+ if (details.reason) {
3940
+ const reason = details.reason;
3941
+ if (reason === "Not authorized" || reason === "Not approved issuer") {
3942
+ return { code: "ACCESS_DENIED", message: reason };
3943
+ }
3944
+ return { code: "REVERT", message: reason };
3945
+ }
3946
+ if (details.revert?.args) {
3947
+ const name = details.revert.name ?? details.revert.signature ?? "";
3948
+ if (name.includes("AccessControl")) {
3949
+ const [account, role] = details.revert.args;
3950
+ return {
3951
+ code: "ACCESS_DENIED",
3952
+ message: `AccessControl: account ${account} missing role ${role}`
3953
+ };
3954
+ }
3955
+ }
3956
+ return null;
3957
+ }
3958
+ var ERROR_SELECTOR_MAP;
3933
3959
  var init_errorMap = __esm({
3934
3960
  "src/sdk/rpc/errorMap.ts"() {
3935
3961
  "use strict";
3962
+ ERROR_SELECTOR_MAP = {
3963
+ // OpenZeppelin AccessControlUnauthorizedAccount(address account, bytes32 role)
3964
+ // keccak256("AccessControlUnauthorizedAccount(address,bytes32)") = 0x761f22a3
3965
+ // ethers v6 surfaces this as 0xe2517d3f in CALL_EXCEPTION details
3966
+ "0xe2517d3f": {
3967
+ code: "ACCESS_DENIED",
3968
+ message: "AccessControl: missing required role"
3969
+ },
3970
+ "0x761f22a3": {
3971
+ code: "ACCESS_DENIED",
3972
+ message: "AccessControl: missing required role"
3973
+ },
3974
+ // OpenZeppelin AccessControl: account is missing role
3975
+ "0x4e6f6c52": {
3976
+ code: "ACCESS_DENIED",
3977
+ message: "AccessControl: account is missing role"
3978
+ },
3979
+ // ERC20: insufficient balance
3980
+ "0x13be252b": {
3981
+ code: "INSUFFICIENT_BALANCE",
3982
+ message: "ERC20: transfer amount exceeds balance"
3983
+ },
3984
+ // ERC20: insufficient allowance
3985
+ "0xf4d708f0": {
3986
+ code: "INSUFFICIENT_ALLOWANCE",
3987
+ message: "ERC20: insufficient allowance"
3988
+ },
3989
+ // Pausable: paused
3990
+ "0x8d1c0a00": {
3991
+ code: "PAUSED",
3992
+ message: "Pausable: paused"
3993
+ },
3994
+ // ERC20: invalid sender
3995
+ "0xdf24fd05": {
3996
+ code: "INVALID_SENDER",
3997
+ message: "ERC20: invalid sender"
3998
+ },
3999
+ // ERC20: blacklisted
4000
+ "0x12d1b5d1": {
4001
+ code: "BLACKLISTED",
4002
+ message: "ERC20: sender is blacklisted"
4003
+ },
4004
+ // Isometry platform / factory custom errors (observed)
4005
+ "0x1e55aece": {
4006
+ code: "NOT_APPROVED_ISSUER",
4007
+ message: "Not an approved issuer"
4008
+ },
4009
+ "0xf2d4620b": {
4010
+ code: "FACTORY_SYMBOL_EXISTS",
4011
+ message: "Factory: symbol already exists"
4012
+ },
4013
+ "0x3b800a46": {
4014
+ code: "ZERO_ADDRESS",
4015
+ message: "Address cannot be zero"
4016
+ }
4017
+ };
3936
4018
  }
3937
4019
  });
3938
4020
 
3939
4021
  // src/sdk/rpc/writeExecutor.ts
4022
+ function makeWriteMeta(command) {
4023
+ return {
4024
+ chainId: 11155111,
4025
+ source: "rpc",
4026
+ timestamp: Math.floor(Date.now() / 1e3),
4027
+ ...command ? { command } : {}
4028
+ };
4029
+ }
4030
+ function formatWriteResult(result, opts, meta) {
4031
+ if (opts.json) {
4032
+ const out = { ok: result.ok };
4033
+ if (result.ok) {
4034
+ if (opts.simulate) {
4035
+ const r2 = result;
4036
+ Object.assign(out, { estimatedGas: r2.estimatedGas, functionFragment: r2.functionFragment, params: r2.params });
4037
+ } else {
4038
+ const r2 = result;
4039
+ Object.assign(out, { receipt: r2.receipt });
4040
+ }
4041
+ } else {
4042
+ const r2 = result;
4043
+ Object.assign(out, { code: r2.code, message: r2.message });
4044
+ if (r2.selector) Object.assign(out, { selector: r2.selector });
4045
+ }
4046
+ if (meta) Object.assign(out, { meta });
4047
+ return JSON.stringify(
4048
+ out,
4049
+ (_key, value) => typeof value === "bigint" ? value.toString() : value,
4050
+ 2
4051
+ );
4052
+ }
4053
+ if (!result.ok) {
4054
+ return `\u274C [${result.code}] ${result.message}`;
4055
+ }
4056
+ if (opts.simulate) {
4057
+ const sim = result;
4058
+ return `\u2705 Simulation passed
4059
+ Estimated gas: ${sim.estimatedGas.toLocaleString()}`;
4060
+ }
4061
+ const exec = result;
4062
+ const r = exec.receipt;
4063
+ const ok = r.status === 1;
4064
+ return [
4065
+ `${ok ? "\u2705" : "\u274C"} Transaction ${ok ? "confirmed" : "FAILED"}`,
4066
+ ` Tx Hash ${r.txHash}`,
4067
+ ` Block ${r.blockNumber ?? "pending"}`,
4068
+ ` From ${r.from}`,
4069
+ ` To ${r.to ?? "N/A"}`,
4070
+ ` Gas Used ${r.gasUsed.toLocaleString()}`,
4071
+ ` Status ${ok ? "success" : "reverted"}`
4072
+ ].join("\n");
4073
+ }
4074
+ var WriteExecutor;
3940
4075
  var init_writeExecutor = __esm({
3941
4076
  "src/sdk/rpc/writeExecutor.ts"() {
3942
4077
  "use strict";
3943
4078
  init_errorMap();
4079
+ WriteExecutor = class {
4080
+ constructor(config2) {
4081
+ this.config = config2;
4082
+ }
4083
+ config;
4084
+ /** Dry-run: estimate gas without signing. Returns gas estimate or decoded error. */
4085
+ async simulate(call) {
4086
+ if (this.config.wallet.mode === "readonly") {
4087
+ return {
4088
+ ok: false,
4089
+ code: "NO_SIGNER",
4090
+ message: `Cannot simulate: wallet is read-only. Set ISOMETRY_PRIVATE_KEY to enable write operations.`
4091
+ };
4092
+ }
4093
+ try {
4094
+ const fn = this.config.contract.getFunction(call.method);
4095
+ const gasEstimate = await fn.estimateGas(...call.args, call.overrides ?? {});
4096
+ const params = {};
4097
+ fn.fragment.inputs.forEach((input, i) => {
4098
+ params[input.name || `arg${i}`] = call.args[i];
4099
+ });
4100
+ return {
4101
+ ok: true,
4102
+ estimatedGas: gasEstimate,
4103
+ functionFragment: `${call.method}(${fn.fragment.inputs.map((i) => i.type).join(",")})`,
4104
+ params
4105
+ };
4106
+ } catch (err) {
4107
+ const decoded = this.parseRevertError(err);
4108
+ return {
4109
+ ok: false,
4110
+ code: "SIMULATION_FAILED",
4111
+ message: `[simulate] ${decoded.message}`,
4112
+ details: err,
4113
+ ...decoded.selector ? { selector: decoded.selector } : {}
4114
+ };
4115
+ }
4116
+ }
4117
+ /** Execute: sign and broadcast, wait for receipt. */
4118
+ async execute(call, confirmations = 1) {
4119
+ if (this.config.wallet.mode === "readonly") {
4120
+ return {
4121
+ ok: false,
4122
+ code: "NO_SIGNER",
4123
+ message: `Cannot execute: wallet is read-only. Set ISOMETRY_PRIVATE_KEY to enable write operations.`
4124
+ };
4125
+ }
4126
+ if (!this.config.wallet.signer) {
4127
+ return {
4128
+ ok: false,
4129
+ code: "NO_SIGNER",
4130
+ message: "Wallet has no signer."
4131
+ };
4132
+ }
4133
+ try {
4134
+ const contract = this.config.contract.connect(this.config.wallet.signer);
4135
+ const fn = contract.getFunction(call.method);
4136
+ const tx = await fn.populateTransaction(...call.args, call.overrides ?? {});
4137
+ const signedTx = await this.config.wallet.signer.sendTransaction(tx);
4138
+ const _receipt = await signedTx.wait(confirmations);
4139
+ if (!_receipt) {
4140
+ return { ok: false, code: "RPC_ERROR", message: "Transaction receipt is null" };
4141
+ }
4142
+ return {
4143
+ ok: true,
4144
+ receipt: {
4145
+ txHash: _receipt.hash,
4146
+ blockNumber: _receipt.blockNumber,
4147
+ blockHash: _receipt.blockHash ?? null,
4148
+ status: _receipt.status ?? null,
4149
+ gasUsed: _receipt.gasUsed,
4150
+ effectiveGasPrice: _receipt.effectiveGasPrice ?? 0n,
4151
+ from: _receipt.from,
4152
+ to: _receipt.to ?? null,
4153
+ nonce: _receipt.nonce,
4154
+ logs: _receipt.logs.map((log) => ({
4155
+ address: log.address,
4156
+ topics: [...log.topics],
4157
+ data: log.data,
4158
+ blockNumber: log.blockNumber
4159
+ }))
4160
+ }
4161
+ };
4162
+ } catch (err) {
4163
+ const decoded = this.parseRevertError(err);
4164
+ return {
4165
+ ok: false,
4166
+ code: decoded.code,
4167
+ message: decoded.message,
4168
+ details: err,
4169
+ ...decoded.selector ? { selector: decoded.selector } : {}
4170
+ };
4171
+ }
4172
+ }
4173
+ /**
4174
+ * Parse a revert error and extract { code, message, selector }.
4175
+ * selector is always included for unknown errors so users can report it.
4176
+ */
4177
+ parseRevertError(err) {
4178
+ let rawSelector;
4179
+ if (err && typeof err === "object") {
4180
+ const errObj = err;
4181
+ const data = errObj.data;
4182
+ if (data && data !== "0x" && data.length >= 10) {
4183
+ rawSelector = data.slice(0, 10).toLowerCase();
4184
+ }
4185
+ }
4186
+ if (err && typeof err === "object") {
4187
+ const decoded = decodeError(err);
4188
+ if (decoded) {
4189
+ return { code: decoded.code, message: decoded.message, selector: rawSelector };
4190
+ }
4191
+ }
4192
+ if (!(err instanceof Error)) {
4193
+ return { code: "UNKNOWN", message: String(err), selector: rawSelector };
4194
+ }
4195
+ const msg = err.message;
4196
+ if (msg.includes("insufficient funds")) return { code: "INSUFFICIENT_BALANCE", message: "insufficient funds for gas", selector: rawSelector };
4197
+ if (msg.includes("nonce")) return { code: "RPC_ERROR", message: "nonce error (tx may already be mined)", selector: rawSelector };
4198
+ if (msg.includes("read-only")) return { code: "NO_SIGNER", message: "wallet is read-only", selector: rawSelector };
4199
+ return { code: "REVERT", message: msg.slice(0, 200), selector: rawSelector };
4200
+ }
4201
+ };
3944
4202
  }
3945
4203
  });
3946
4204
 
@@ -4686,10 +4944,10 @@ function resolveAddresses(env) {
4686
4944
  beacon: env.ISOMETRY_BEACON_ADDRESS ?? DEFAULT_ADDRESSES.beacon
4687
4945
  };
4688
4946
  }
4689
- function createClient2(config2) {
4947
+ function createClient(config2) {
4690
4948
  return new IsometryClient(config2);
4691
4949
  }
4692
- var DEFAULT_ADDRESSES, SDK_VERSION2, IsometryClient;
4950
+ var DEFAULT_ADDRESSES, SDK_VERSION, IsometryClient;
4693
4951
  var init_client2 = __esm({
4694
4952
  "src/sdk/client.ts"() {
4695
4953
  "use strict";
@@ -4704,7 +4962,7 @@ var init_client2 = __esm({
4704
4962
  factory: "0x73D6BC64f4f54F9dF05851216F70F42135d56864",
4705
4963
  beacon: "0x99d6512B5483DFA003F73F737f87e7DAE9482F89"
4706
4964
  };
4707
- SDK_VERSION2 = "0.4.4";
4965
+ SDK_VERSION = "0.4.6";
4708
4966
  IsometryClient = class {
4709
4967
  rpc;
4710
4968
  graph;
@@ -4717,7 +4975,7 @@ var init_client2 = __esm({
4717
4975
  const graphUrl = config2.graphUrl ?? process.env.ISOMETRY_GRAPH_URL ?? "https://console.isometry.network/graph/subgraphs/name/isometry";
4718
4976
  const privateKey = config2.privateKey ?? process.env.ISOMETRY_PRIVATE_KEY;
4719
4977
  this._chainId = config2.chainId ?? parseInt(process.env.ISOMETRY_CHAIN_ID ?? "11155111");
4720
- this._wallet = createWallet2(rpcUrl, privateKey);
4978
+ this._wallet = createWallet(rpcUrl, privateKey);
4721
4979
  this._addresses = config2.addresses ?? resolveAddresses(process.env);
4722
4980
  this.config = {
4723
4981
  chainId: this._chainId,
@@ -4771,13 +5029,13 @@ __export(sdk_exports, {
4771
5029
  PlatformRpcService: () => PlatformRpcService,
4772
5030
  PrivateKeyWallet: () => PrivateKeyWallet,
4773
5031
  ReadOnlyWallet: () => ReadOnlyWallet,
4774
- SDK_VERSION: () => SDK_VERSION2,
5032
+ SDK_VERSION: () => SDK_VERSION,
4775
5033
  StableCoinRpcService: () => StableCoinRpcService,
4776
5034
  TokenHistoryService: () => TokenHistoryService,
4777
- createClient: () => createClient2,
5035
+ createClient: () => createClient,
4778
5036
  createGraphClient: () => createGraphClient,
4779
- createWallet: () => createWallet2,
4780
- getContracts: () => getContracts2,
5037
+ createWallet: () => createWallet,
5038
+ getContracts: () => getContracts,
4781
5039
  getStableCoin: () => getStableCoin
4782
5040
  });
4783
5041
  var init_sdk = __esm({
@@ -4846,17 +5104,172 @@ function registerSystem(parent) {
4846
5104
  var init_system = __esm({
4847
5105
  "src/cli/commands/system.ts"() {
4848
5106
  "use strict";
5107
+ init_sdk();
4849
5108
  init_env();
4850
5109
  loadEnv();
4851
5110
  }
4852
5111
  });
4853
5112
 
5113
+ // src/cli/commands/platformWrite.ts
5114
+ function jsonReplacer2(_key, value) {
5115
+ return typeof value === "bigint" ? value.toString() : value;
5116
+ }
5117
+ async function getPlatformExecutor() {
5118
+ const client = createClient();
5119
+ if (!client.config.privateKey) {
5120
+ return {
5121
+ error: "ISOMETRY_PRIVATE_KEY is not set \u2014 cannot sign transactions",
5122
+ code: "NO_SIGNER"
5123
+ };
5124
+ }
5125
+ const pk = client.config.privateKey;
5126
+ if (!/^0x[0-9a-fA-F]{64}$/.test(pk)) {
5127
+ return { error: "ISOMETRY_PRIVATE_KEY format invalid \u2014 must be 0x-prefixed 64-char hex", code: "INVALID_KEY" };
5128
+ }
5129
+ const wallet = createWallet(client.config.rpcUrl, pk);
5130
+ if (!wallet.signer) {
5131
+ return { error: "Wallet has no signer", code: "NO_SIGNER" };
5132
+ }
5133
+ const { getPlatform: getPlatform2 } = await Promise.resolve().then(() => (init_contracts(), contracts_exports));
5134
+ const platform = getPlatform2(wallet.signer, client.config.addresses);
5135
+ return new WriteExecutor({ wallet, contract: platform });
5136
+ }
5137
+ function outputError(code, message, json) {
5138
+ if (json) {
5139
+ console.log(JSON.stringify({ ok: false, code, message }, jsonReplacer2, 2));
5140
+ } else {
5141
+ console.log(`\u274C [${code}] ${message}`);
5142
+ }
5143
+ }
5144
+ async function addPlatformAdmin(account, opts) {
5145
+ const result = await getPlatformExecutor();
5146
+ if (typeof result === "object" && "error" in result) {
5147
+ outputError(result.code, result.error, opts.json);
5148
+ return;
5149
+ }
5150
+ const executor = result;
5151
+ const memo = opts.memo || `Add platform admin via isometry CLI at ${(/* @__PURE__ */ new Date()).toISOString()}`;
5152
+ const writeResult = opts.simulate ? await executor.simulate({ method: "addPlatformAdmin", args: [account, memo] }) : await executor.execute({ method: "addPlatformAdmin", args: [account, memo] });
5153
+ console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5154
+ }
5155
+ async function removePlatformAdmin(account, opts) {
5156
+ const result = await getPlatformExecutor();
5157
+ if (typeof result === "object" && "error" in result) {
5158
+ outputError(result.code, result.error, opts.json);
5159
+ return;
5160
+ }
5161
+ const executor = result;
5162
+ const memo = opts.memo || `Remove platform admin via isometry CLI at ${(/* @__PURE__ */ new Date()).toISOString()}`;
5163
+ const writeResult = opts.simulate ? await executor.simulate({ method: "removePlatformAdmin", args: [account, memo] }) : await executor.execute({ method: "removePlatformAdmin", args: [account, memo] });
5164
+ console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5165
+ }
5166
+ async function addApprovedIssuer(account, opts) {
5167
+ const result = await getPlatformExecutor();
5168
+ if (typeof result === "object" && "error" in result) {
5169
+ outputError(result.code, result.error, opts.json);
5170
+ return;
5171
+ }
5172
+ const executor = result;
5173
+ const memo = opts.memo || `Add approved issuer via isometry CLI at ${(/* @__PURE__ */ new Date()).toISOString()}`;
5174
+ const writeResult = opts.simulate ? await executor.simulate({ method: "addApprovedIssuer", args: [account, memo] }) : await executor.execute({ method: "addApprovedIssuer", args: [account, memo] });
5175
+ console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5176
+ }
5177
+ async function removeApprovedIssuer(account, opts) {
5178
+ const result = await getPlatformExecutor();
5179
+ if (typeof result === "object" && "error" in result) {
5180
+ outputError(result.code, result.error, opts.json);
5181
+ return;
5182
+ }
5183
+ const executor = result;
5184
+ const memo = opts.memo || `Remove approved issuer via isometry CLI at ${(/* @__PURE__ */ new Date()).toISOString()}`;
5185
+ const writeResult = opts.simulate ? await executor.simulate({ method: "removeApprovedIssuer", args: [account, memo] }) : await executor.execute({ method: "removeApprovedIssuer", args: [account, memo] });
5186
+ console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5187
+ }
5188
+ async function addAccessUser(account, opts) {
5189
+ const result = await getPlatformExecutor();
5190
+ if (typeof result === "object" && "error" in result) {
5191
+ outputError(result.code, result.error, opts.json);
5192
+ return;
5193
+ }
5194
+ const executor = result;
5195
+ const memo = opts.memo || `Add access user via isometry CLI at ${(/* @__PURE__ */ new Date()).toISOString()}`;
5196
+ const writeResult = opts.simulate ? await executor.simulate({ method: "addAccessUser", args: [account, memo] }) : await executor.execute({ method: "addAccessUser", args: [account, memo] });
5197
+ console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5198
+ }
5199
+ async function removeAccessUser(account, opts) {
5200
+ const result = await getPlatformExecutor();
5201
+ if (typeof result === "object" && "error" in result) {
5202
+ outputError(result.code, result.error, opts.json);
5203
+ return;
5204
+ }
5205
+ const executor = result;
5206
+ const memo = opts.memo || `Remove access user via isometry CLI at ${(/* @__PURE__ */ new Date()).toISOString()}`;
5207
+ const writeResult = opts.simulate ? await executor.simulate({ method: "removeAccessUser", args: [account, memo] }) : await executor.execute({ method: "removeAccessUser", args: [account, memo] });
5208
+ console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5209
+ }
5210
+ function registerPlatformWrite(platformCmd) {
5211
+ const admin = platformCmd.command("admin").description("Platform admin management");
5212
+ admin.command("add <account>").description("Add platform admin (requires PLATFORM_ADMIN_ROLE)").option("--simulate", "Simulate without signing").option("--json", "Output as JSON").option("--memo <text>", "Transaction memo", "").action(
5213
+ (account, opts) => addPlatformAdmin(account, {
5214
+ simulate: opts.simulate ?? false,
5215
+ json: opts.json ?? false,
5216
+ memo: opts.memo ?? ""
5217
+ })
5218
+ );
5219
+ admin.command("remove <account>").description("Remove platform admin (requires PLATFORM_ADMIN_ROLE)").option("--simulate", "Simulate without signing").option("--json", "Output as JSON").option("--memo <text>", "Transaction memo", "").action(
5220
+ (account, opts) => removePlatformAdmin(account, {
5221
+ simulate: opts.simulate ?? false,
5222
+ json: opts.json ?? false,
5223
+ memo: opts.memo ?? ""
5224
+ })
5225
+ );
5226
+ const issuer = platformCmd.command("issuer").description("Approved issuer management");
5227
+ issuer.command("add <account>").description("Add approved issuer (requires PLATFORM_ADMIN_ROLE)").option("--simulate", "Simulate without signing").option("--json", "Output as JSON").option("--memo <text>", "Transaction memo", "").action(
5228
+ (account, opts) => addApprovedIssuer(account, {
5229
+ simulate: opts.simulate ?? false,
5230
+ json: opts.json ?? false,
5231
+ memo: opts.memo ?? ""
5232
+ })
5233
+ );
5234
+ issuer.command("remove <account>").description("Remove approved issuer (requires PLATFORM_ADMIN_ROLE)").option("--simulate", "Simulate without signing").option("--json", "Output as JSON").option("--memo <text>", "Transaction memo", "").action(
5235
+ (account, opts) => removeApprovedIssuer(account, {
5236
+ simulate: opts.simulate ?? false,
5237
+ json: opts.json ?? false,
5238
+ memo: opts.memo ?? ""
5239
+ })
5240
+ );
5241
+ const access = platformCmd.command("access").description("Access user management");
5242
+ access.command("add <account>").description("Add access user (requires PLATFORM_ADMIN_ROLE)").option("--simulate", "Simulate without signing").option("--json", "Output as JSON").option("--memo <text>", "Transaction memo", "").action(
5243
+ (account, opts) => addAccessUser(account, {
5244
+ simulate: opts.simulate ?? false,
5245
+ json: opts.json ?? false,
5246
+ memo: opts.memo ?? ""
5247
+ })
5248
+ );
5249
+ access.command("remove <account>").description("Remove access user (requires PLATFORM_ADMIN_ROLE)").option("--simulate", "Simulate without signing").option("--json", "Output as JSON").option("--memo <text>", "Transaction memo", "").action(
5250
+ (account, opts) => removeAccessUser(account, {
5251
+ simulate: opts.simulate ?? false,
5252
+ json: opts.json ?? false,
5253
+ memo: opts.memo ?? ""
5254
+ })
5255
+ );
5256
+ }
5257
+ var init_platformWrite = __esm({
5258
+ "src/cli/commands/platformWrite.ts"() {
5259
+ "use strict";
5260
+ init_env();
5261
+ init_sdk();
5262
+ init_writeExecutor();
5263
+ loadEnv();
5264
+ }
5265
+ });
5266
+
4854
5267
  // src/cli/commands/platform.ts
4855
5268
  var platform_exports = {};
4856
5269
  __export(platform_exports, {
4857
5270
  registerPlatform: () => registerPlatform
4858
5271
  });
4859
- function jsonReplacer2(_key, value) {
5272
+ function jsonReplacer3(_key, value) {
4860
5273
  return typeof value === "bigint" ? value.toString() : value;
4861
5274
  }
4862
5275
  async function info(json) {
@@ -4889,7 +5302,7 @@ async function info(json) {
4889
5302
  }))
4890
5303
  };
4891
5304
  if (json) {
4892
- console.log(JSON.stringify({ ok: true, data }, jsonReplacer2, 2));
5305
+ console.log(JSON.stringify({ ok: true, data }, jsonReplacer3, 2));
4893
5306
  } else {
4894
5307
  console.log(`Platform Paused ${data.paused ? "YES \u274C" : "No \u2705"}`);
4895
5308
  console.log(`Token Count ${data.tokenCount}`);
@@ -4906,7 +5319,7 @@ async function tokens(json) {
4906
5319
  const client = createClient();
4907
5320
  const tokenAddrs = await client.rpc.platform.getAllTokens();
4908
5321
  if (json) {
4909
- console.log(JSON.stringify({ ok: true, data: { tokens: tokenAddrs } }, jsonReplacer2, 2));
5322
+ console.log(JSON.stringify({ ok: true, data: { tokens: tokenAddrs } }, jsonReplacer3, 2));
4910
5323
  } else {
4911
5324
  console.log(`Registered tokens: ${tokenAddrs.length}`);
4912
5325
  tokenAddrs.forEach((a) => console.log(` ${a}`));
@@ -4922,12 +5335,14 @@ var init_platform2 = __esm({
4922
5335
  "src/cli/commands/platform.ts"() {
4923
5336
  "use strict";
4924
5337
  init_env();
5338
+ init_sdk();
5339
+ init_platformWrite();
4925
5340
  loadEnv();
4926
5341
  }
4927
5342
  });
4928
5343
 
4929
5344
  // src/cli/commands/tokenWrite.ts
4930
- function jsonReplacer3(_key, value) {
5345
+ function jsonReplacer4(_key, value) {
4931
5346
  return typeof value === "bigint" ? value.toString() : value;
4932
5347
  }
4933
5348
  async function getTokenExecutor(tokenAddress) {
@@ -4954,9 +5369,9 @@ async function getTokenExecutor(tokenAddress) {
4954
5369
  const executor = new WriteExecutor({ wallet, contract: tokenContract });
4955
5370
  return { executor };
4956
5371
  }
4957
- function outputError(code, message, json) {
5372
+ function outputError2(code, message, json) {
4958
5373
  if (json) {
4959
- console.log(JSON.stringify({ ok: false, code, message }, jsonReplacer3, 2));
5374
+ console.log(JSON.stringify({ ok: false, code, message }, jsonReplacer4, 2));
4960
5375
  } else {
4961
5376
  console.log(`\u274C [${code}] ${message}`);
4962
5377
  }
@@ -4969,7 +5384,7 @@ async function tokenMint(tokenAddress, to, amount, opts) {
4969
5384
  const writeResult = opts.simulate ? await executor.simulate({ method: "mint", args: [to, BigInt(amount), memo] }) : await executor.execute({ method: "mint", args: [to, BigInt(amount), memo] });
4970
5385
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
4971
5386
  } else {
4972
- outputError(result.code, result.error, opts.json);
5387
+ outputError2(result.code, result.error, opts.json);
4973
5388
  }
4974
5389
  }
4975
5390
  async function tokenBurn(tokenAddress, amount, opts) {
@@ -4980,7 +5395,7 @@ async function tokenBurn(tokenAddress, amount, opts) {
4980
5395
  const writeResult = opts.simulate ? await executor.simulate({ method: "burn", args: [BigInt(amount), memo] }) : await executor.execute({ method: "burn", args: [BigInt(amount), memo] });
4981
5396
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
4982
5397
  } else {
4983
- outputError(result.code, result.error, opts.json);
5398
+ outputError2(result.code, result.error, opts.json);
4984
5399
  }
4985
5400
  }
4986
5401
  async function tokenPause(tokenAddress, opts) {
@@ -4991,7 +5406,7 @@ async function tokenPause(tokenAddress, opts) {
4991
5406
  const writeResult = opts.simulate ? await executor.simulate({ method: "pause", args: [memo] }) : await executor.execute({ method: "pause", args: [memo] });
4992
5407
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
4993
5408
  } else {
4994
- outputError(result.code, result.error, opts.json);
5409
+ outputError2(result.code, result.error, opts.json);
4995
5410
  }
4996
5411
  }
4997
5412
  async function tokenUnpause(tokenAddress, opts) {
@@ -5002,7 +5417,7 @@ async function tokenUnpause(tokenAddress, opts) {
5002
5417
  const writeResult = opts.simulate ? await executor.simulate({ method: "unpause", args: [memo] }) : await executor.execute({ method: "unpause", args: [memo] });
5003
5418
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5004
5419
  } else {
5005
- outputError(result.code, result.error, opts.json);
5420
+ outputError2(result.code, result.error, opts.json);
5006
5421
  }
5007
5422
  }
5008
5423
  async function blacklistAdd(tokenAddress, user, opts) {
@@ -5013,7 +5428,7 @@ async function blacklistAdd(tokenAddress, user, opts) {
5013
5428
  const writeResult = opts.simulate ? await executor.simulate({ method: "blacklist", args: [user, memo] }) : await executor.execute({ method: "blacklist", args: [user, memo] });
5014
5429
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5015
5430
  } else {
5016
- outputError(result.code, result.error, opts.json);
5431
+ outputError2(result.code, result.error, opts.json);
5017
5432
  }
5018
5433
  }
5019
5434
  async function blacklistRemove(tokenAddress, user, opts) {
@@ -5024,7 +5439,7 @@ async function blacklistRemove(tokenAddress, user, opts) {
5024
5439
  const writeResult = opts.simulate ? await executor.simulate({ method: "unBlacklist", args: [user, memo] }) : await executor.execute({ method: "unBlacklist", args: [user, memo] });
5025
5440
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5026
5441
  } else {
5027
- outputError(result.code, result.error, opts.json);
5442
+ outputError2(result.code, result.error, opts.json);
5028
5443
  }
5029
5444
  }
5030
5445
  async function addBlacklistManager(tokenAddress, account, opts) {
@@ -5035,7 +5450,7 @@ async function addBlacklistManager(tokenAddress, account, opts) {
5035
5450
  const writeResult = opts.simulate ? await executor.simulate({ method: "addBlacklistManager", args: [account, memo] }) : await executor.execute({ method: "addBlacklistManager", args: [account, memo] });
5036
5451
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5037
5452
  } else {
5038
- outputError(result.code, result.error, opts.json);
5453
+ outputError2(result.code, result.error, opts.json);
5039
5454
  }
5040
5455
  }
5041
5456
  async function removeBlacklistManager(tokenAddress, account, opts) {
@@ -5046,7 +5461,7 @@ async function removeBlacklistManager(tokenAddress, account, opts) {
5046
5461
  const writeResult = opts.simulate ? await executor.simulate({ method: "removeBlacklistManager", args: [account, memo] }) : await executor.execute({ method: "removeBlacklistManager", args: [account, memo] });
5047
5462
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5048
5463
  } else {
5049
- outputError(result.code, result.error, opts.json);
5464
+ outputError2(result.code, result.error, opts.json);
5050
5465
  }
5051
5466
  }
5052
5467
  async function addMinter(tokenAddress, minter, allowance, opts) {
@@ -5057,7 +5472,7 @@ async function addMinter(tokenAddress, minter, allowance, opts) {
5057
5472
  const writeResult = opts.simulate ? await executor.simulate({ method: "addMinter", args: [minter, BigInt(allowance), memo] }) : await executor.execute({ method: "addMinter", args: [minter, BigInt(allowance), memo] });
5058
5473
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5059
5474
  } else {
5060
- outputError(result.code, result.error, opts.json);
5475
+ outputError2(result.code, result.error, opts.json);
5061
5476
  }
5062
5477
  }
5063
5478
  async function removeMinter(tokenAddress, minter, opts) {
@@ -5068,7 +5483,7 @@ async function removeMinter(tokenAddress, minter, opts) {
5068
5483
  const writeResult = opts.simulate ? await executor.simulate({ method: "removeMinter", args: [minter, memo] }) : await executor.execute({ method: "removeMinter", args: [minter, memo] });
5069
5484
  console.log(formatWriteResult(writeResult, { simulate: opts.simulate, json: opts.json }, makeWriteMeta()));
5070
5485
  } else {
5071
- outputError(result.code, result.error, opts.json);
5486
+ outputError2(result.code, result.error, opts.json);
5072
5487
  }
5073
5488
  }
5074
5489
  function registerTokenWrite(token) {
@@ -5150,6 +5565,8 @@ var init_tokenWrite = __esm({
5150
5565
  "src/cli/commands/tokenWrite.ts"() {
5151
5566
  "use strict";
5152
5567
  init_env();
5568
+ init_sdk();
5569
+ init_writeExecutor();
5153
5570
  loadEnv();
5154
5571
  }
5155
5572
  });
@@ -5159,14 +5576,14 @@ var token_exports = {};
5159
5576
  __export(token_exports, {
5160
5577
  registerToken: () => registerToken
5161
5578
  });
5579
+ function jsonReplacer5(_key, value) {
5580
+ return typeof value === "bigint" ? value.toString() : value;
5581
+ }
5162
5582
  function formatBigInt(v) {
5163
5583
  return v.toString();
5164
5584
  }
5165
- function jsonReplacer4(_key, value) {
5166
- return typeof value === "bigint" ? value.toString() : value;
5167
- }
5168
5585
  async function tokenInfo(addr, json) {
5169
- const client = createClient2();
5586
+ const client = createClient();
5170
5587
  const [info2, stats] = await Promise.all([
5171
5588
  client.rpc.token.getTokenInfo(addr),
5172
5589
  client.rpc.token.getTokenStats(addr)
@@ -5186,7 +5603,7 @@ async function tokenInfo(addr, json) {
5186
5603
  blacklistCount: parseBigIntToNumber(stats.blacklistCount.toString())
5187
5604
  };
5188
5605
  if (json) {
5189
- console.log(JSON.stringify({ ok: true, data }, jsonReplacer4, 2));
5606
+ console.log(JSON.stringify({ ok: true, data }, jsonReplacer5, 2));
5190
5607
  } else {
5191
5608
  console.log(`Address ${data.address}`);
5192
5609
  console.log(`Name ${data.name}`);
@@ -5202,7 +5619,7 @@ async function tokenInfo(addr, json) {
5202
5619
  }
5203
5620
  }
5204
5621
  async function tokenStats(addr, json) {
5205
- const client = createClient2();
5622
+ const client = createClient();
5206
5623
  const stats = await client.rpc.token.getTokenStats(addr);
5207
5624
  const net = BigInt(stats.totalMinted) - BigInt(stats.totalBurned);
5208
5625
  const data = {
@@ -5216,7 +5633,7 @@ async function tokenStats(addr, json) {
5216
5633
  blacklistCount: parseBigIntToNumber(stats.blacklistCount.toString())
5217
5634
  };
5218
5635
  if (json) {
5219
- console.log(JSON.stringify({ ok: true, data }, jsonReplacer4, 2));
5636
+ console.log(JSON.stringify({ ok: true, data }, jsonReplacer5, 2));
5220
5637
  } else {
5221
5638
  console.log(`Address ${data.address}`);
5222
5639
  console.log(`Holders ${data.holdersTotal}`);
@@ -5229,7 +5646,7 @@ async function tokenStats(addr, json) {
5229
5646
  }
5230
5647
  }
5231
5648
  async function tokenRoles(addr, account, json) {
5232
- const client = createClient2();
5649
+ const client = createClient();
5233
5650
  const roles = await client.rpc.token.getUserRoles(addr, account);
5234
5651
  const data = {
5235
5652
  token: roles.address,
@@ -5241,7 +5658,7 @@ async function tokenRoles(addr, account, json) {
5241
5658
  isMasterStatus: roles.isMasterStatus
5242
5659
  };
5243
5660
  if (json) {
5244
- console.log(JSON.stringify({ ok: true, data }, jsonReplacer4, 2));
5661
+ console.log(JSON.stringify({ ok: true, data }, jsonReplacer5, 2));
5245
5662
  } else {
5246
5663
  console.log(`Token ${data.token}`);
5247
5664
  console.log(`Account ${data.account}`);
@@ -5253,7 +5670,7 @@ async function tokenRoles(addr, account, json) {
5253
5670
  }
5254
5671
  }
5255
5672
  async function tokenHistory(addr, first, json) {
5256
- const client = createClient2();
5673
+ const client = createClient();
5257
5674
  const [mints, burns] = await Promise.all([
5258
5675
  client.graph.token.getMintHistory(addr, first, 0),
5259
5676
  client.graph.token.getBurnHistory(addr, first, 0)
@@ -5276,7 +5693,7 @@ async function tokenHistory(addr, first, json) {
5276
5693
  ];
5277
5694
  events.sort((a, b) => BigInt(a.block) > BigInt(b.block) ? -1 : 1);
5278
5695
  if (json) {
5279
- console.log(JSON.stringify({ ok: true, data: { events } }, jsonReplacer4, 2));
5696
+ console.log(JSON.stringify({ ok: true, data: { events } }, jsonReplacer5, 2));
5280
5697
  } else {
5281
5698
  console.log(`Token ${addr}`);
5282
5699
  console.log(`Mint events ${mints.length} Burn events ${burns.length}`);
@@ -5286,10 +5703,10 @@ async function tokenHistory(addr, first, json) {
5286
5703
  }
5287
5704
  }
5288
5705
  async function tokenMintHistory(addr, first, json) {
5289
- const client = createClient2();
5706
+ const client = createClient();
5290
5707
  const events = await client.graph.token.getMintHistory(addr, first, 0);
5291
5708
  if (json) {
5292
- console.log(JSON.stringify({ ok: true, data: { events } }, jsonReplacer4, 2));
5709
+ console.log(JSON.stringify({ ok: true, data: { events } }, jsonReplacer5, 2));
5293
5710
  } else {
5294
5711
  console.log(`Token ${addr} \u2014 Mint History (${events.length} events)`);
5295
5712
  events.slice(0, 10).forEach((e) => {
@@ -5298,10 +5715,10 @@ async function tokenMintHistory(addr, first, json) {
5298
5715
  }
5299
5716
  }
5300
5717
  async function tokenBurnHistory(addr, first, json) {
5301
- const client = createClient2();
5718
+ const client = createClient();
5302
5719
  const events = await client.graph.token.getBurnHistory(addr, first, 0);
5303
5720
  if (json) {
5304
- console.log(JSON.stringify({ ok: true, data: { events } }, jsonReplacer4, 2));
5721
+ console.log(JSON.stringify({ ok: true, data: { events } }, jsonReplacer5, 2));
5305
5722
  } else {
5306
5723
  console.log(`Token ${addr} \u2014 Burn History (${events.length} events)`);
5307
5724
  events.slice(0, 10).forEach((e) => {
@@ -5310,7 +5727,7 @@ async function tokenBurnHistory(addr, first, json) {
5310
5727
  }
5311
5728
  }
5312
5729
  async function tokenPauseHistory(addr, first, json) {
5313
- const client = createClient2();
5730
+ const client = createClient();
5314
5731
  const [pauseEvts, pausedEvts, unpausedEvts] = await Promise.all([
5315
5732
  client.graph.token.getPauseHistory(addr, first, 0),
5316
5733
  client.graph.token.getPausedByOwnerHistory(addr, first, 0),
@@ -5320,7 +5737,7 @@ async function tokenPauseHistory(addr, first, json) {
5320
5737
  console.log(JSON.stringify({
5321
5738
  ok: true,
5322
5739
  data: { pauseEvents: pauseEvts, pausedByOwnerEvents: pausedEvts, unpausedByOwnerEvents: unpausedEvts }
5323
- }, null, 2));
5740
+ }, jsonReplacer5, 2));
5324
5741
  } else {
5325
5742
  console.log(`Token ${addr} \u2014 Pause History`);
5326
5743
  console.log(`Pause events ${pauseEvts.length}`);
@@ -5363,7 +5780,7 @@ var factory_exports = {};
5363
5780
  __export(factory_exports, {
5364
5781
  registerFactory: () => registerFactory
5365
5782
  });
5366
- function jsonReplacer5(_key, value) {
5783
+ function jsonReplacer6(_key, value) {
5367
5784
  return typeof value === "bigint" ? value.toString() : value;
5368
5785
  }
5369
5786
  async function factoryInfo(json) {
@@ -5379,7 +5796,7 @@ async function factoryInfo(json) {
5379
5796
  chainId: client.config.chainId
5380
5797
  };
5381
5798
  if (json) {
5382
- console.log(JSON.stringify({ ok: true, data }, jsonReplacer5, 2));
5799
+ console.log(JSON.stringify({ ok: true, data }, jsonReplacer6, 2));
5383
5800
  } else {
5384
5801
  console.log(`Beacon ${data.beacon}`);
5385
5802
  console.log(`Platform ${data.platform}`);
@@ -5392,18 +5809,18 @@ async function factoryCreate(name, symbol, opts) {
5392
5809
  const client = createClient();
5393
5810
  if (!client.config.addresses.factory) {
5394
5811
  const msg = "ISOMETRY_FACTORY_ADDRESS is not configured";
5395
- console.log(opts.json ? JSON.stringify({ ok: false, code: "NOT_CONFIGURED", message: msg }, jsonReplacer5, 2) : `\u274C ${msg}`);
5812
+ console.log(opts.json ? JSON.stringify({ ok: false, code: "NOT_CONFIGURED", message: msg }, jsonReplacer6, 2) : `\u274C ${msg}`);
5396
5813
  return;
5397
5814
  }
5398
5815
  if (!client.config.privateKey) {
5399
5816
  const msg = "ISOMETRY_PRIVATE_KEY is not set \u2014 cannot sign transactions";
5400
- console.log(opts.json ? JSON.stringify({ ok: false, code: "NO_SIGNER", message: msg }, jsonReplacer5, 2) : `\u274C ${msg}`);
5817
+ console.log(opts.json ? JSON.stringify({ ok: false, code: "NO_SIGNER", message: msg }, jsonReplacer6, 2) : `\u274C ${msg}`);
5401
5818
  return;
5402
5819
  }
5403
5820
  const wallet = createWallet(client.config.rpcUrl, client.config.privateKey);
5404
5821
  if (!wallet.signer) {
5405
5822
  const msg = "Wallet has no signer \u2014 check ISOMETRY_PRIVATE_KEY";
5406
- console.log(opts.json ? JSON.stringify({ ok: false, code: "NO_SIGNER", message: msg }, jsonReplacer5, 2) : `\u274C ${msg}`);
5823
+ console.log(opts.json ? JSON.stringify({ ok: false, code: "NO_SIGNER", message: msg }, jsonReplacer6, 2) : `\u274C ${msg}`);
5407
5824
  return;
5408
5825
  }
5409
5826
  const contracts = getContracts(client.config.addresses, wallet.signer);
@@ -5434,16 +5851,20 @@ var init_factory2 = __esm({
5434
5851
  "src/cli/commands/factory.ts"() {
5435
5852
  "use strict";
5436
5853
  init_env();
5854
+ init_sdk();
5855
+ init_writeExecutor();
5437
5856
  loadEnv();
5438
5857
  }
5439
5858
  });
5440
5859
 
5441
5860
  // src/cli/index.ts
5861
+ init_env();
5442
5862
  import { Command } from "commander";
5443
5863
  import { readFileSync } from "fs";
5444
5864
  import { resolve as resolve2 } from "path";
5445
5865
  import { fileURLToPath as fileURLToPath2 } from "url";
5446
5866
  var __dirname2 = fileURLToPath2(new URL(".", import.meta.url));
5867
+ loadEnv();
5447
5868
  var pkg = JSON.parse(
5448
5869
  readFileSync(resolve2(__dirname2, "../package.json"), "utf-8")
5449
5870
  );