@msafe/sui-app-store 0.0.10 → 0.0.11

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.js CHANGED
@@ -34,12 +34,306 @@ __export(src_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(src_exports);
36
36
 
37
- // src/apps/msafe-core/helper.ts
38
- var import_sui3_utils4 = require("@msafe/sui3-utils");
39
-
40
- // src/apps/msafe-core/coin-transfer.ts
37
+ // src/apps/mpay/helper.ts
41
38
  var import_sui3_utils = require("@msafe/sui3-utils");
42
39
 
40
+ // src/apps/mpay/config/dev.json
41
+ var dev_exports = {};
42
+ __export(dev_exports, {
43
+ contractId: () => contractId,
44
+ default: () => dev_default,
45
+ feeObjId: () => feeObjId,
46
+ roleObjId: () => roleObjId,
47
+ status: () => status,
48
+ transaction: () => transaction,
49
+ upgradeCapObjId: () => upgradeCapObjId,
50
+ vaultObjId: () => vaultObjId
51
+ });
52
+ var transaction = "DiBZq4UmVVYiRL6ZJmFKYoHcxtxqrhsCXSkFyT7wUr3j";
53
+ var status = "success";
54
+ var contractId = "0x81c960dc653975fbd0072deca8afb92d322898c911622898ba1b2e3ad0c4bd8d";
55
+ var roleObjId = "0xc6ec0bdee0bb59a72077e9acd2f42457043cf47080b3d3fad4d39abf28bba63a";
56
+ var vaultObjId = "0xbc4021387fbac149119fd24e92be9e58f745774292f3a2a12e2ac6daf5363e1d";
57
+ var feeObjId = "0x4178f63970fe2daeb256dc5730ad172e82b3e8eb45f31b33e0daae72cd35e1e1";
58
+ var upgradeCapObjId = "0xe1e9aa7d222d151bfe6dd83358b0d7fdcb11260f710800cfaf7ccc1b1e245115";
59
+ var dev_default = {
60
+ transaction,
61
+ status,
62
+ contractId,
63
+ roleObjId,
64
+ vaultObjId,
65
+ feeObjId,
66
+ upgradeCapObjId
67
+ };
68
+
69
+ // src/apps/mpay/config/prod.json
70
+ var prod_exports = {};
71
+ __export(prod_exports, {
72
+ contractId: () => contractId2,
73
+ default: () => prod_default,
74
+ feeObjId: () => feeObjId2,
75
+ roleObjId: () => roleObjId2,
76
+ status: () => status2,
77
+ transaction: () => transaction2,
78
+ upgradeCapObjId: () => upgradeCapObjId2,
79
+ vaultObjId: () => vaultObjId2
80
+ });
81
+ var transaction2 = "855FNDV8o8Z3fWULPnQo9qdhLJpsg7wZrkCpNyfw9KfB";
82
+ var status2 = "success";
83
+ var contractId2 = "0xc357c3985e8fb875d6b37141497af660779aa1bab0ec489b2213efd74067d1fa";
84
+ var roleObjId2 = "0x5ab49bdf9fd1413e328ef242b3f8d83dde791b38a0b627bfc87fb25c010d34f1";
85
+ var vaultObjId2 = "0xb483558770d8eb26007f193b75db40f0a45f2e36863a687625885d4de6993378";
86
+ var feeObjId2 = "0x48453fc4d7cde3fe35aad89e5dfb496608a6a55ea529a1c0274681a808627f94";
87
+ var upgradeCapObjId2 = "0x34279779a0d0d36bd5044b04830d607fa1b0ecf316548c8ac3a44151e4f1a42a";
88
+ var prod_default = {
89
+ transaction: transaction2,
90
+ status: status2,
91
+ contractId: contractId2,
92
+ roleObjId: roleObjId2,
93
+ vaultObjId: vaultObjId2,
94
+ feeObjId: feeObjId2,
95
+ upgradeCapObjId: upgradeCapObjId2
96
+ };
97
+
98
+ // src/apps/mpay/common/env.ts
99
+ var DEV_RPC_ENDPOINT = "https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD";
100
+ var STG_RPC_ENDPOINT = "https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD";
101
+ var PREV_RPC_ENDPOINT = "https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7";
102
+ var PROD_RPC_ENDPOINT = "https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7";
103
+ var DEV_BE_API = "https://bc3p6l5unl.execute-api.us-west-1.amazonaws.com/prod";
104
+ var STG_BE_API = "https://rolsbkota7.execute-api.us-west-1.amazonaws.com/prod";
105
+ var PREV_BE_API = "https://6p6mkx33ne.execute-api.us-west-1.amazonaws.com/prod";
106
+ var PROD_BE_API = "https://xrae3mrjv5.execute-api.us-west-1.amazonaws.com/prod";
107
+ var CONTRACT_DEV = dev_exports;
108
+ var CONTRACT_PROD = prod_exports;
109
+ var ENV_CONFIG = /* @__PURE__ */ new Map([
110
+ [
111
+ "dev" /* dev */,
112
+ {
113
+ env: "dev" /* dev */,
114
+ rpc: {
115
+ url: DEV_RPC_ENDPOINT
116
+ },
117
+ backend: {
118
+ url: DEV_BE_API
119
+ },
120
+ contract: CONTRACT_DEV
121
+ }
122
+ ],
123
+ [
124
+ "stg" /* stg */,
125
+ {
126
+ env: "stg" /* stg */,
127
+ rpc: {
128
+ url: STG_RPC_ENDPOINT
129
+ },
130
+ backend: {
131
+ url: STG_BE_API
132
+ },
133
+ contract: CONTRACT_DEV
134
+ }
135
+ ],
136
+ [
137
+ "prev" /* prev */,
138
+ {
139
+ env: "prev" /* prev */,
140
+ rpc: {
141
+ url: PREV_RPC_ENDPOINT
142
+ },
143
+ backend: {
144
+ url: PREV_BE_API
145
+ },
146
+ contract: CONTRACT_PROD
147
+ }
148
+ ],
149
+ [
150
+ "prod" /* prod */,
151
+ {
152
+ env: "prod" /* prod */,
153
+ rpc: {
154
+ url: PROD_RPC_ENDPOINT
155
+ },
156
+ backend: {
157
+ url: PROD_BE_API
158
+ },
159
+ contract: CONTRACT_PROD
160
+ }
161
+ ]
162
+ ]);
163
+ function getConfig(env, options) {
164
+ const ec = ENV_CONFIG.get(env);
165
+ if (!ec) {
166
+ throw new Error(`Env not supported: ${env}`);
167
+ }
168
+ if (options && options.rpc) {
169
+ ec.rpc = options.rpc;
170
+ }
171
+ if (options && options.backend) {
172
+ ec.backend = options.backend;
173
+ }
174
+ if (options && options.contract) {
175
+ ec.contract = options.contract;
176
+ }
177
+ return ec;
178
+ }
179
+
180
+ // src/apps/mpay/common/globals.ts
181
+ var import_client = require("@mysten/sui.js/client");
182
+
183
+ // src/apps/mpay/error/base.ts
184
+ var MPayError = class extends Error {
185
+ mpayErrorCode;
186
+ context;
187
+ constructor(mpayErrorCode, msg, options = {}) {
188
+ const { cause, context } = options;
189
+ if (cause) {
190
+ super(`[MPay] ${msg}: ${cause}`);
191
+ } else {
192
+ super(`[MPay] ${msg}`);
193
+ }
194
+ this.mpayErrorCode = mpayErrorCode;
195
+ this.context = context;
196
+ }
197
+ };
198
+
199
+ // src/apps/mpay/error/NoBackendError.ts
200
+ var NoBackendError = class extends MPayError {
201
+ constructor() {
202
+ super(11 /* NoBackend */, "Backend is not specified");
203
+ }
204
+ };
205
+
206
+ // src/apps/mpay/error/WalletNotConnectedError.ts
207
+ var WalletNotConnectedError = class extends MPayError {
208
+ constructor() {
209
+ super(1 /* walletNotConnected */, "Wallet not connected");
210
+ }
211
+ };
212
+
213
+ // src/apps/mpay/stream/backend.ts
214
+ var import_axios = __toESM(require("axios"));
215
+
216
+ // src/apps/mpay/error/BackendError.ts
217
+ var BackendError = class extends MPayError {
218
+ constructor(msg, context) {
219
+ super(10 /* BackendError */, msg, { context });
220
+ }
221
+ };
222
+
223
+ // src/apps/mpay/stream/backend.ts
224
+ var Backend = class _Backend {
225
+ constructor(apiURL) {
226
+ this.apiURL = apiURL;
227
+ }
228
+ static parseResponseData(response) {
229
+ if (response instanceof import_axios.AxiosError) {
230
+ throw new BackendError(response.response?.statusText);
231
+ }
232
+ if (response.status === 200) {
233
+ if (response.data.success) {
234
+ return response.data.data;
235
+ }
236
+ throw new BackendError(response.data.code);
237
+ }
238
+ throw new BackendError(response.status.toString());
239
+ }
240
+ async getIncomingStreams(recipient, options) {
241
+ const res = await import_axios.default.post(`${this.apiURL}/stream`, {
242
+ recipient,
243
+ ...options
244
+ });
245
+ return _Backend.parseResponseData(res);
246
+ }
247
+ async getOutgoingStreams(sender, options) {
248
+ const res = await import_axios.default.post(`${this.apiURL}/stream`, {
249
+ sender,
250
+ ...options
251
+ });
252
+ return _Backend.parseResponseData(res);
253
+ }
254
+ async getStreamHistory(query) {
255
+ const res = await import_axios.default.post(`${this.apiURL}/stream-events`, query);
256
+ const paginatedData = _Backend.parseResponseData(res);
257
+ paginatedData.data.forEach((event) => {
258
+ const formalizedEvent = event;
259
+ if (formalizedEvent.data.type === "create_stream") {
260
+ formalizedEvent.data.balance = BigInt(formalizedEvent.data.balance);
261
+ } else if (formalizedEvent.data.type === "cancel_stream") {
262
+ formalizedEvent.data.withdrawAmount = BigInt(formalizedEvent.data.withdrawAmount);
263
+ } else if (formalizedEvent.data.type === "claim" || formalizedEvent.data.type === "auto_claim") {
264
+ formalizedEvent.data.claimAmount = BigInt(formalizedEvent.data.claimAmount);
265
+ } else if (formalizedEvent.data.type === "set_auto_claim") {
266
+ formalizedEvent.data.enabled = !!formalizedEvent.data.enabled;
267
+ }
268
+ formalizedEvent.createdAt = new Date(formalizedEvent.createdAt);
269
+ return formalizedEvent;
270
+ });
271
+ return paginatedData;
272
+ }
273
+ async getAllCoinTypes(address) {
274
+ const res = await import_axios.default.post(`${this.apiURL}/stream-info`, { address });
275
+ return _Backend.parseResponseData(res);
276
+ }
277
+ async getAllRecipients(sender, options) {
278
+ const res = await import_axios.default.post(`${this.apiURL}/stream-info`, { sender, status: options });
279
+ return _Backend.parseResponseData(res);
280
+ }
281
+ async getAllSenders(recipient, options) {
282
+ const res = await import_axios.default.post(`${this.apiURL}/stream-info`, { recipient, status: options });
283
+ return _Backend.parseResponseData(res);
284
+ }
285
+ };
286
+
287
+ // src/apps/mpay/common/globals.ts
288
+ var Globals = class _Globals {
289
+ signer;
290
+ suiClient;
291
+ envConfig;
292
+ _backend;
293
+ constructor(envConfig) {
294
+ this.envConfig = envConfig;
295
+ this.suiClient = new import_client.SuiClient({ url: envConfig.rpc.url });
296
+ if (envConfig.backend) {
297
+ this._backend = new Backend(envConfig.backend.url);
298
+ }
299
+ }
300
+ static new(env, options) {
301
+ const ec = getConfig(env, options);
302
+ return new _Globals(ec);
303
+ }
304
+ get walletType() {
305
+ if (!this.wallet) {
306
+ return "disconnected";
307
+ }
308
+ return this.wallet.type;
309
+ }
310
+ get backend() {
311
+ if (!this._backend) {
312
+ throw new NoBackendError();
313
+ }
314
+ return this._backend;
315
+ }
316
+ // Used for test cases
317
+ set backend(b) {
318
+ this._backend = b;
319
+ }
320
+ connectWallet(wallet) {
321
+ this.signer = wallet;
322
+ }
323
+ disconnect() {
324
+ this.signer = void 0;
325
+ }
326
+ get wallet() {
327
+ if (!this.signer) {
328
+ throw new WalletNotConnectedError();
329
+ }
330
+ return this.signer;
331
+ }
332
+ async walletAddress() {
333
+ return this.wallet.address();
334
+ }
335
+ };
336
+
43
337
  // src/apps/msafe-core/intention.ts
44
338
  var import_sort_keys_recursive = __toESM(require("sort-keys-recursive"));
45
339
  var CoreBaseIntention = class {
@@ -54,7 +348,2167 @@ var CoreBaseIntention = class {
54
348
  }
55
349
  };
56
350
 
351
+ // src/apps/mpay/stream/client.ts
352
+ var import_utils9 = require("@mysten/sui.js/utils");
353
+
354
+ // src/apps/mpay/stream/helper.ts
355
+ var import_utils5 = require("@mysten/sui.js/utils");
356
+ var import_luxon = require("luxon");
357
+
358
+ // src/apps/mpay/builder/MPayBuilder.ts
359
+ var import_transactions3 = require("@mysten/sui.js/transactions");
360
+
361
+ // src/apps/mpay/builder/CreateStreamHelper.ts
362
+ var import_transactions = require("@mysten/sui.js/transactions");
363
+ var import_utils3 = require("@mysten/sui.js/utils");
364
+
365
+ // src/apps/mpay/builder/const.ts
366
+ var FEE_NUMERATOR = 50n;
367
+ var FEE_DENOMINATOR = 10000n;
368
+ var CLAIM_FEE_NUMERATOR = 25n;
369
+ var FLAT_FEE_SUI = 100000000n;
370
+
371
+ // src/apps/mpay/common/transaction.ts
372
+ var MoveObject = class {
373
+ constructor(object) {
374
+ this.object = object;
375
+ }
376
+ moveArg(txb) {
377
+ return txb.object(this.object);
378
+ }
379
+ };
380
+ var ObjectVector = class {
381
+ constructor(objects) {
382
+ this.objects = objects;
383
+ }
384
+ moveArgs(txb) {
385
+ return txb.makeMoveVec({ objects: this.objects.map((o) => txb.object(o)) });
386
+ }
387
+ };
388
+ var ResultRef = class _ResultRef {
389
+ constructor(result) {
390
+ this.result = result;
391
+ return new Proxy(this, {
392
+ set() {
393
+ throw new Error("The transaction result is a proxy, and does not support setting properties directly");
394
+ },
395
+ get(target, property) {
396
+ if (property in target) {
397
+ return Reflect.get(target, property);
398
+ }
399
+ const nestedResultFor = (resultIndex2) => new _ResultRef(target.result[resultIndex2]);
400
+ if (property === Symbol.iterator) {
401
+ return function* () {
402
+ let i = 0;
403
+ while (true) {
404
+ yield nestedResultFor(i);
405
+ i++;
406
+ }
407
+ };
408
+ }
409
+ if (typeof property === "symbol") {
410
+ return;
411
+ }
412
+ const resultIndex = parseInt(property, 10);
413
+ if (Number.isNaN(resultIndex) || resultIndex < 0) {
414
+ return;
415
+ }
416
+ return nestedResultFor(resultIndex);
417
+ }
418
+ });
419
+ }
420
+ moveArg() {
421
+ return this.result;
422
+ }
423
+ };
424
+
425
+ // src/apps/mpay/contract/InspectViewer.ts
426
+ var import_utils = require("@mysten/sui.js/utils");
427
+
428
+ // src/apps/mpay/error/InvalidRpcResultError.ts
429
+ var InvalidRpcResultError = class extends MPayError {
430
+ constructor(msg, ctx) {
431
+ super(3 /* InvalidRpcResult */, msg, { context: ctx });
432
+ }
433
+ };
434
+
435
+ // src/apps/mpay/contract/InspectViewer.ts
436
+ var InspectViewer = class {
437
+ constructor(results) {
438
+ this.results = results;
439
+ }
440
+ callResult(index) {
441
+ return this.results.results[index];
442
+ }
443
+ returnValue(returned, index) {
444
+ return returned.returnValues[index];
445
+ }
446
+ getValue(callIndex = 0, returnIndex = 0) {
447
+ const callResult = this.callResult(callIndex);
448
+ return this.returnValue(callResult, returnIndex);
449
+ }
450
+ getAddress(callIndex = 0, returnIndex = 0) {
451
+ const [value, type] = this.getValue(callIndex, returnIndex);
452
+ if (type !== "address") {
453
+ throw new InvalidRpcResultError("Invalid contract return type.", {
454
+ ctx: {
455
+ expectType: "address",
456
+ gotType: type
457
+ }
458
+ });
459
+ }
460
+ return (0, import_utils.normalizeSuiAddress)(Buffer.from(value).toString("hex"));
461
+ }
462
+ getU64(callIndex = 0, returnIndex = 0) {
463
+ const [value, type] = this.getValue(callIndex, returnIndex);
464
+ if (type !== "u64") {
465
+ throw new InvalidRpcResultError("Invalid contract return type.", {
466
+ ctx: {
467
+ expectType: "u64",
468
+ gotType: type
469
+ }
470
+ });
471
+ }
472
+ return Buffer.from(value).readBigInt64LE();
473
+ }
474
+ };
475
+
476
+ // src/apps/mpay/stream/metadata.ts
477
+ var import_bcs = require("@mysten/sui.js/bcs");
478
+
479
+ // src/apps/mpay/error/InvalidInputError.ts
480
+ var InvalidInputError = class extends MPayError {
481
+ constructor(msg, fieldKey, fieldValue) {
482
+ super(2 /* InvalidInput */, `Invalid input: ${msg}`, {
483
+ context: {
484
+ fieldKey,
485
+ fieldValue
486
+ }
487
+ });
488
+ }
489
+ };
490
+
491
+ // src/apps/mpay/stream/metadata.ts
492
+ var metadataBcsType = {
493
+ groupId: "string",
494
+ name: "string"
495
+ };
496
+ var MAX_NAME_SIZE = 64;
497
+ function encodeMetadata(metadata) {
498
+ validateMetadata(metadata);
499
+ return import_bcs.bcs.ser(metadataBcsType, metadata).toString("base64");
500
+ }
501
+ function decodeMetadata(metaStr) {
502
+ const metadata = import_bcs.bcs.de(metadataBcsType, metaStr, "base64");
503
+ validateMetadata(metadata);
504
+ return metadata;
505
+ }
506
+ function validateMetadata(metadata) {
507
+ if (!isAsciiString(metadata.name)) {
508
+ throw new InvalidInputError("Invalid metadata: Name contains unknown character");
509
+ }
510
+ if (!isAsciiString(metadata.groupId)) {
511
+ throw new InvalidInputError("Invalid metadata: Group ID contains unknown character");
512
+ }
513
+ if (metadata.name.length > MAX_NAME_SIZE) {
514
+ throw new InvalidInputError("Invalid metadata: Name exceed max length 64");
515
+ }
516
+ }
517
+ function isAsciiString(str) {
518
+ const asciiPattern = /^[\x00-\x7F]+$/;
519
+ return asciiPattern.test(str);
520
+ }
521
+
522
+ // src/apps/mpay/sui/utils.ts
523
+ var import_utils2 = require("@mysten/sui.js/utils");
524
+ function isSameCoinType(type1, type2) {
525
+ return (0, import_utils2.normalizeStructTag)(type1) === (0, import_utils2.normalizeStructTag)(type2);
526
+ }
527
+ function isSameTarget(target1, target2) {
528
+ return (0, import_utils2.normalizeStructTag)(target1) === (0, import_utils2.normalizeStructTag)(target2);
529
+ }
530
+
531
+ // src/apps/mpay/types/wallet.ts
532
+ var GAS_OBJECT_SPEC = "txn.gas";
533
+
534
+ // src/apps/mpay/utils/random.ts
535
+ function generateGroupId() {
536
+ return "nanoid()";
537
+ }
538
+
539
+ // src/apps/mpay/builder/CreateStreamHelper.ts
540
+ var CreateStreamHelper = class _CreateStreamHelper {
541
+ constructor(globals, feeContract, streamContract) {
542
+ this.globals = globals;
543
+ this.feeContract = feeContract;
544
+ this.streamContract = streamContract;
545
+ }
546
+ static convertCreateStreamInfoToInternal(info) {
547
+ return {
548
+ metadata: encodeMetadata({
549
+ name: info.name,
550
+ groupId: generateGroupId()
551
+ }),
552
+ coinType: (0, import_utils3.normalizeStructTag)(info.coinType),
553
+ recipients: info.recipients.map((recipient) => ({
554
+ address: recipient.address,
555
+ cliffAmount: recipient.cliffAmount,
556
+ amountPerEpoch: recipient.amountPerStep
557
+ })),
558
+ epochInterval: info.interval,
559
+ numberEpoch: info.steps,
560
+ startTime: info.startTimeMs,
561
+ cancelable: info.cancelable
562
+ };
563
+ }
564
+ async buildCreateStreamTransactionBlock(info) {
565
+ const txb = new import_transactions.TransactionBlock();
566
+ const paymentWithFee = this.calculateFeesInternal(info);
567
+ const coinReqs = this.getCreateStreamCoinRequests(info, paymentWithFee);
568
+ const coinResp = await this.wallet.requestCoins(coinReqs);
569
+ const paymentMergedObject = await this.addMergeCoins(txb, coinResp[0]);
570
+ let flatFeeMergedObject;
571
+ if (coinReqs.length > 1) {
572
+ flatFeeMergedObject = await this.addMergeCoins(txb, coinResp[1]);
573
+ } else {
574
+ flatFeeMergedObject = paymentMergedObject;
575
+ }
576
+ for (let i = 0; i < info.recipients.length; i++) {
577
+ const recipient = info.recipients[i];
578
+ const paymentAmount = this.amountForRecipient(recipient, info.numberEpoch);
579
+ const feeAmount = this.getStreamFeeLocal(paymentAmount);
580
+ const [paymentCoin] = txb.splitCoins(paymentMergedObject, [txb.pure(paymentAmount + feeAmount, "u64")]);
581
+ const [flatFeeCoin] = txb.splitCoins(flatFeeMergedObject, [txb.pure(this.flatSuiFee, "u64")]);
582
+ this.streamContract.createStream(txb, {
583
+ paymentCoin: new ResultRef(paymentCoin),
584
+ flatFeeCoin: new ResultRef(flatFeeCoin),
585
+ metadata: info.metadata,
586
+ recipient: recipient.address,
587
+ timeStart: info.startTime,
588
+ cliff: recipient.cliffAmount,
589
+ epochInterval: info.epochInterval,
590
+ numEpoch: info.numberEpoch,
591
+ amountPerEpoch: recipient.amountPerEpoch,
592
+ cancelable: info.cancelable,
593
+ coinType: info.coinType
594
+ });
595
+ }
596
+ return txb;
597
+ }
598
+ calculateCreateStreamFees(createInfo) {
599
+ const infoInternal = _CreateStreamHelper.convertCreateStreamInfoToInternal(createInfo);
600
+ return this.calculateFeesInternal(infoInternal);
601
+ }
602
+ feeParams() {
603
+ return {
604
+ createFeePercent: {
605
+ numerator: FEE_NUMERATOR,
606
+ denominator: FEE_DENOMINATOR
607
+ },
608
+ claimFeePercent: {
609
+ numerator: CLAIM_FEE_NUMERATOR,
610
+ denominator: FEE_DENOMINATOR
611
+ },
612
+ flatFeePerStream: FLAT_FEE_SUI
613
+ };
614
+ }
615
+ async addMergeCoins(txb, coins) {
616
+ let mergedCoin;
617
+ if (coins.mergedCoins && coins.mergedCoins.length) {
618
+ txb.mergeCoins(
619
+ txb.object(coins.primaryCoin),
620
+ coins.mergedCoins.map((coinId) => txb.object(coinId))
621
+ );
622
+ mergedCoin = txb.object(coins.primaryCoin);
623
+ } else if (coins.primaryCoin === GAS_OBJECT_SPEC) {
624
+ mergedCoin = txb.gas;
625
+ } else {
626
+ mergedCoin = txb.object(coins.primaryCoin);
627
+ }
628
+ return mergedCoin;
629
+ }
630
+ getCreateStreamCoinRequests(info, payment) {
631
+ const streamCoinType = info.coinType;
632
+ if (isSameCoinType(streamCoinType, import_utils3.SUI_TYPE_ARG)) {
633
+ return [
634
+ {
635
+ coinType: streamCoinType,
636
+ amount: payment.totalAmount + payment.streamFeeAmount + payment.flatFeeAmount
637
+ }
638
+ ];
639
+ }
640
+ return [
641
+ {
642
+ coinType: streamCoinType,
643
+ amount: payment.totalAmount + payment.streamFeeAmount
644
+ },
645
+ {
646
+ coinType: import_utils3.SUI_TYPE_ARG,
647
+ amount: payment.flatFeeAmount
648
+ }
649
+ ];
650
+ }
651
+ calculateFeesInternal(info) {
652
+ const streamPayment = info.recipients.reduce(
653
+ (sum, recipient) => {
654
+ const totalAmount = this.amountForRecipient(recipient, info.numberEpoch);
655
+ const fee = this.getStreamFeeLocal(totalAmount);
656
+ return {
657
+ totalAmount: sum.totalAmount + totalAmount,
658
+ streamFeeAmount: sum.streamFeeAmount + fee
659
+ };
660
+ },
661
+ {
662
+ totalAmount: 0n,
663
+ streamFeeAmount: 0n
664
+ }
665
+ );
666
+ const flatFeeAmount = BigInt(info.recipients.length) * this.flatSuiFee;
667
+ return {
668
+ flatFeeAmount,
669
+ ...streamPayment
670
+ };
671
+ }
672
+ amountForRecipient(recipient, numEpoch) {
673
+ return recipient.amountPerEpoch * numEpoch + recipient.cliffAmount;
674
+ }
675
+ get flatSuiFee() {
676
+ return FLAT_FEE_SUI;
677
+ }
678
+ getStreamFeeLocal(streamAmount) {
679
+ return streamAmount * FEE_NUMERATOR / FEE_DENOMINATOR;
680
+ }
681
+ async getStreamFeeRemote(streamAmount) {
682
+ const txb = this.feeContract.streamingFee(new import_transactions.TransactionBlock(), streamAmount);
683
+ const res = await this.globals.suiClient.devInspectTransactionBlock({
684
+ sender: await this.globals.walletAddress(),
685
+ transactionBlock: txb
686
+ });
687
+ const iv = new InspectViewer(res);
688
+ return iv.getU64();
689
+ }
690
+ get wallet() {
691
+ return this.globals.wallet;
692
+ }
693
+ };
694
+
695
+ // src/apps/mpay/contract/BaseContract.ts
696
+ var import_transactions2 = require("@mysten/sui.js/transactions");
697
+
698
+ // src/apps/mpay/const.ts
699
+ var CLOCK_ID = "0x0000000000000000000000000000000000000000000000000000000000000006";
700
+
701
+ // src/apps/mpay/contract/BaseContract.ts
702
+ var BaseContract = class {
703
+ constructor(moduleName, config, globals) {
704
+ this.moduleName = moduleName;
705
+ this.config = config;
706
+ this.globals = globals;
707
+ }
708
+ addContractCall(txb, input) {
709
+ const target = `${this.config.contractId}::${this.moduleName}::${input.method}`;
710
+ txb.add(
711
+ import_transactions2.Transactions.MoveCall({
712
+ target,
713
+ arguments: input.arguments.map((arg) => {
714
+ if (arg instanceof ObjectVector) {
715
+ return arg.moveArgs(txb);
716
+ }
717
+ if (arg instanceof MoveObject) {
718
+ return arg.moveArg(txb);
719
+ }
720
+ if (arg instanceof ResultRef) {
721
+ return arg.moveArg();
722
+ }
723
+ return txb.pure(arg);
724
+ }),
725
+ typeArguments: input.typeArgs
726
+ })
727
+ );
728
+ return txb;
729
+ }
730
+ addTransactionBlock(txb, target, callArgs = [], typeArgs = []) {
731
+ txb.add(
732
+ import_transactions2.Transactions.MoveCall({
733
+ target,
734
+ arguments: callArgs.map((arg) => {
735
+ if (arg instanceof ObjectVector) {
736
+ return arg.moveArgs(txb);
737
+ }
738
+ if (arg instanceof MoveObject) {
739
+ return arg.moveArg(txb);
740
+ }
741
+ if (arg instanceof ResultRef) {
742
+ return arg.moveArg();
743
+ }
744
+ return txb.pure(arg);
745
+ }),
746
+ typeArguments: typeArgs
747
+ })
748
+ );
749
+ }
750
+ makeObject(object) {
751
+ return typeof object === "string" ? new MoveObject(object) : object;
752
+ }
753
+ vaultObject() {
754
+ return new MoveObject(this.config.vaultObjId);
755
+ }
756
+ roleObject() {
757
+ return new MoveObject(this.config.roleObjId);
758
+ }
759
+ feeObject() {
760
+ return new MoveObject(this.config.feeObjId);
761
+ }
762
+ clockObject() {
763
+ return new MoveObject(CLOCK_ID);
764
+ }
765
+ };
766
+
767
+ // src/apps/mpay/contract/FeeContract.ts
768
+ var FeeContract = class _FeeContract extends BaseContract {
769
+ constructor(config, globals) {
770
+ super(_FeeContract.ModuleName, config, globals);
771
+ this.config = config;
772
+ this.globals = globals;
773
+ }
774
+ static ModuleName = "fee_module";
775
+ static MethodName = {
776
+ set_streaming_fee: "set_streaming_fee",
777
+ set_claim_fee: "set_claim_fee",
778
+ set_streaming_flat_fee: "set_streaming_flat_fee",
779
+ streaming_flat_fee: "streaming_flat_fee",
780
+ streaming_fee: "streaming_fee",
781
+ claim_fee: "claim_fee",
782
+ fee_denominator: "fee_denominator"
783
+ };
784
+ setStreamingFee(txb, createFeeNumerator) {
785
+ const roleObject = this.roleObject();
786
+ const feeObject = this.feeObject();
787
+ return this.addContractCall(txb, {
788
+ method: _FeeContract.MethodName.set_streaming_fee,
789
+ arguments: [roleObject, feeObject, createFeeNumerator],
790
+ typeArgs: []
791
+ });
792
+ }
793
+ setStreamingFlatFee(txb, flatFee) {
794
+ const roleObject = this.roleObject();
795
+ const feeObject = this.feeObject();
796
+ return this.addContractCall(txb, {
797
+ method: _FeeContract.MethodName.set_streaming_flat_fee,
798
+ arguments: [roleObject, feeObject, flatFee],
799
+ typeArgs: []
800
+ });
801
+ }
802
+ setClaimFee(txb, claimFee) {
803
+ const roleObject = this.roleObject();
804
+ const feeObject = this.feeObject();
805
+ return this.addContractCall(txb, {
806
+ method: _FeeContract.MethodName.set_claim_fee,
807
+ arguments: [roleObject, feeObject, claimFee],
808
+ typeArgs: []
809
+ });
810
+ }
811
+ streamingFee(txb, amount) {
812
+ const feeObject = this.feeObject();
813
+ return this.addContractCall(txb, {
814
+ method: _FeeContract.MethodName.streaming_fee,
815
+ arguments: [feeObject, amount],
816
+ typeArgs: []
817
+ });
818
+ }
819
+ claimFee(txb, amount) {
820
+ return this.addContractCall(txb, {
821
+ method: _FeeContract.MethodName.claim_fee,
822
+ arguments: [this.feeObject(), amount],
823
+ typeArgs: []
824
+ });
825
+ }
826
+ feeDenominator(txb) {
827
+ return this.addContractCall(txb, {
828
+ method: _FeeContract.MethodName.fee_denominator,
829
+ arguments: [this.feeObject()],
830
+ typeArgs: []
831
+ });
832
+ }
833
+ };
834
+
835
+ // src/apps/mpay/contract/StreamContract.ts
836
+ var StreamContract = class _StreamContract extends BaseContract {
837
+ constructor(config, globals) {
838
+ super(_StreamContract.ModuleName, config, globals);
839
+ this.config = config;
840
+ this.globals = globals;
841
+ }
842
+ static ModuleName = "stream";
843
+ static MethodName = {
844
+ create_stream: "create_stream",
845
+ set_auto_claim: "set_auto_claim",
846
+ cancel_stream: "cancel_stream",
847
+ claim_stream: "claim_stream",
848
+ claim_stream_by_proxy: "claim_stream_by_proxy",
849
+ stream_current_epoch: "stream_current_epoch",
850
+ now_milli_seconds: "now_milli_seconds"
851
+ };
852
+ createStream(txb, input) {
853
+ const feeObject = this.feeObject();
854
+ const vaultObject = this.vaultObject();
855
+ const paymentCoinObject = this.makeObject(input.paymentCoin);
856
+ const flatFeeObject = this.makeObject(input.flatFeeCoin);
857
+ const clockObject = this.clockObject();
858
+ return this.addContractCall(txb, {
859
+ method: _StreamContract.MethodName.create_stream,
860
+ arguments: [
861
+ feeObject,
862
+ vaultObject,
863
+ paymentCoinObject,
864
+ flatFeeObject,
865
+ input.metadata,
866
+ input.recipient,
867
+ input.timeStart,
868
+ input.cliff,
869
+ input.epochInterval,
870
+ input.numEpoch,
871
+ input.amountPerEpoch,
872
+ input.cancelable,
873
+ clockObject
874
+ ],
875
+ typeArgs: [input.coinType]
876
+ });
877
+ }
878
+ setAutoClaim(txb, input) {
879
+ const streamObject = this.makeObject(input.streamId);
880
+ return this.addContractCall(txb, {
881
+ method: _StreamContract.MethodName.set_auto_claim,
882
+ arguments: [streamObject, input.enabled],
883
+ typeArgs: [input.coinType]
884
+ });
885
+ }
886
+ cancelStream(txb, input) {
887
+ const streamObject = this.makeObject(input.streamId);
888
+ const clockObject = this.clockObject();
889
+ return this.addContractCall(txb, {
890
+ method: _StreamContract.MethodName.cancel_stream,
891
+ arguments: [streamObject, clockObject],
892
+ typeArgs: [input.coinType]
893
+ });
894
+ }
895
+ claimStream(txb, input) {
896
+ const streamObject = this.makeObject(input.streamId);
897
+ const clockObject = this.clockObject();
898
+ return this.addContractCall(txb, {
899
+ method: _StreamContract.MethodName.claim_stream,
900
+ arguments: [streamObject, clockObject],
901
+ typeArgs: [input.coinType]
902
+ });
903
+ }
904
+ claimStreamByProxy(txb, input) {
905
+ const streamObject = this.makeObject(input.streamId);
906
+ const vaultObject = this.vaultObject();
907
+ const feeObject = this.feeObject();
908
+ const clockObject = this.clockObject();
909
+ return this.addContractCall(txb, {
910
+ method: _StreamContract.MethodName.claim_stream_by_proxy,
911
+ arguments: [streamObject, vaultObject, feeObject, clockObject],
912
+ typeArgs: [input.coinType]
913
+ });
914
+ }
915
+ get createStreamTarget() {
916
+ return `${this.config.contractId}::${_StreamContract.ModuleName}::${_StreamContract.MethodName.create_stream}`;
917
+ }
918
+ get setAutoClaimTarget() {
919
+ return `${this.config.contractId}::${_StreamContract.ModuleName}::${_StreamContract.MethodName.set_auto_claim}`;
920
+ }
921
+ get cancelStreamTarget() {
922
+ return `${this.config.contractId}::${_StreamContract.ModuleName}::${_StreamContract.MethodName.cancel_stream}`;
923
+ }
924
+ get claimStreamTarget() {
925
+ return `${this.config.contractId}::${_StreamContract.ModuleName}::${_StreamContract.MethodName.claim_stream}`;
926
+ }
927
+ get claimStreamByProxyTarget() {
928
+ return `${this.config.contractId}::${_StreamContract.ModuleName}::${_StreamContract.MethodName.claim_stream_by_proxy}`;
929
+ }
930
+ };
931
+
932
+ // src/apps/mpay/builder/MPayBuilder.ts
933
+ var MPayBuilder = class {
934
+ constructor(globals) {
935
+ this.globals = globals;
936
+ const config = globals.envConfig.contract;
937
+ this.feeContract = new FeeContract(config, globals);
938
+ this.streamContract = new StreamContract(config, globals);
939
+ }
940
+ feeContract;
941
+ streamContract;
942
+ async createStreams(info) {
943
+ const infoInternal = CreateStreamHelper.convertCreateStreamInfoToInternal(info);
944
+ return this.createStreamHelper().buildCreateStreamTransactionBlock(infoInternal);
945
+ }
946
+ createStreamHelper() {
947
+ return new CreateStreamHelper(this.globals, this.feeContract, this.streamContract);
948
+ }
949
+ setAutoClaim(streamId, enabled, coinType) {
950
+ const txb = new import_transactions3.TransactionBlock();
951
+ return this.streamContract.setAutoClaim(txb, {
952
+ streamId,
953
+ enabled,
954
+ coinType
955
+ });
956
+ }
957
+ claimStream(streamId, coinType) {
958
+ const txb = new import_transactions3.TransactionBlock();
959
+ return this.streamContract.claimStream(txb, {
960
+ streamId,
961
+ coinType
962
+ });
963
+ }
964
+ claimStreamByProxy(streamId, coinType) {
965
+ const txb = new import_transactions3.TransactionBlock();
966
+ return this.streamContract.claimStreamByProxy(txb, {
967
+ streamId,
968
+ coinType
969
+ });
970
+ }
971
+ cancelStream(streamId, coinType) {
972
+ const txb = new import_transactions3.TransactionBlock();
973
+ this.streamContract.cancelStream(txb, {
974
+ streamId,
975
+ coinType
976
+ });
977
+ return txb;
978
+ }
979
+ };
980
+
981
+ // src/apps/mpay/error/TransactionFailedError.ts
982
+ var TransactionFailedError = class extends MPayError {
983
+ constructor(status3, msg) {
984
+ super(12 /* TransactionFailed */, `Transaction failed: ${msg}`, {
985
+ context: {
986
+ status: status3,
987
+ msg
988
+ }
989
+ });
990
+ }
991
+ };
992
+
993
+ // src/apps/mpay/stream/helper.ts
994
+ var MIN_INTERVAL_MS = 1e3;
995
+ var MPayHelper = class {
996
+ constructor(globals) {
997
+ this.globals = globals;
998
+ this.coinMetaHelper = new CoinMetaHelper(globals.suiClient);
999
+ this.createStreamHelper = new MPayBuilder(globals).createStreamHelper();
1000
+ }
1001
+ coinMetaHelper;
1002
+ createStreamHelper;
1003
+ getStreamIdsFromCreateStreamResponse(res) {
1004
+ if (res.effects?.status.status !== "success") {
1005
+ throw new TransactionFailedError(res.effects?.status.status, res.effects?.status.error);
1006
+ }
1007
+ return res.objectChanges.filter(
1008
+ (change) => change.type === "created" && change.objectType.startsWith(`${this.globals.envConfig.contract.contractId}::stream::Stream`)
1009
+ ).map((change) => change.objectId);
1010
+ }
1011
+ calculateCreateStreamFees(info) {
1012
+ return this.createStreamHelper.calculateCreateStreamFees(info);
1013
+ }
1014
+ feeParams() {
1015
+ return this.createStreamHelper.feeParams();
1016
+ }
1017
+ calculateStreamAmount(input) {
1018
+ if (input.steps === 0n) {
1019
+ throw new InvalidInputError("Invalid stream steps: 0");
1020
+ }
1021
+ const cliffFraction = input.cliff ? input.cliff : {
1022
+ numerator: 0n,
1023
+ denominator: 100n
1024
+ };
1025
+ const cliffAmount = input.totalAmount * cliffFraction.numerator / cliffFraction.denominator;
1026
+ const amountPerStep = (input.totalAmount - cliffAmount) / input.steps;
1027
+ const realTotalAmount = amountPerStep * input.steps + cliffAmount;
1028
+ const res = {
1029
+ realTotalAmount,
1030
+ cliffAmount,
1031
+ amountPerStep
1032
+ };
1033
+ this.validateStreamAmount(res, input.totalAmount);
1034
+ return res;
1035
+ }
1036
+ calculateTimelineByInterval(input) {
1037
+ if (input.steps === 0n) {
1038
+ throw new InvalidInputError("Invalid stream steps: 0");
1039
+ }
1040
+ const timeEnd = input.timeStart.plus(input.interval.toMillis() * Number(input.steps));
1041
+ const res = {
1042
+ timeStart: input.timeStart,
1043
+ timeEnd,
1044
+ interval: input.interval,
1045
+ steps: input.steps
1046
+ };
1047
+ this.validateTimeline(res);
1048
+ return res;
1049
+ }
1050
+ calculateTimelineByTotalDuration(input) {
1051
+ if (input.steps === 0n) {
1052
+ throw new InvalidInputError("Invalid stream steps: 0");
1053
+ }
1054
+ const intervalMilli = BigInt(input.total.toMillis()) / input.steps;
1055
+ const timeEnd = input.timeStart.plus(import_luxon.Duration.fromMillis(Number(intervalMilli * input.steps)));
1056
+ const res = {
1057
+ timeStart: input.timeStart,
1058
+ timeEnd,
1059
+ interval: import_luxon.Duration.fromMillis(Number(intervalMilli)),
1060
+ steps: input.steps
1061
+ };
1062
+ this.validateTimeline(res);
1063
+ return res;
1064
+ }
1065
+ async getBalance(address, coinType) {
1066
+ const balance = await this.globals.suiClient.getBalance({
1067
+ owner: address,
1068
+ coinType
1069
+ });
1070
+ const coinMeta = await this.getCoinMeta(coinType);
1071
+ return {
1072
+ ...balance,
1073
+ coinType: (0, import_utils5.normalizeStructTag)(balance.coinType),
1074
+ coinMeta
1075
+ };
1076
+ }
1077
+ async getAllBalance(address) {
1078
+ const allBalance = await this.globals.suiClient.getAllBalances({
1079
+ owner: address
1080
+ });
1081
+ const coinMetas = await Promise.all(allBalance.map((bal) => this.getCoinMeta(bal.coinType)));
1082
+ return allBalance.map((bal, i) => ({
1083
+ ...bal,
1084
+ coinType: (0, import_utils5.normalizeStructTag)(bal.coinType),
1085
+ coinMeta: coinMetas[i]
1086
+ }));
1087
+ }
1088
+ async getCoinMeta(coinType) {
1089
+ return this.coinMetaHelper.getCoinMeta(coinType);
1090
+ }
1091
+ async simulateTransactionBlock(txb) {
1092
+ return this.globals.suiClient.devInspectTransactionBlock({
1093
+ transactionBlock: txb,
1094
+ sender: await this.globals.wallet.address()
1095
+ });
1096
+ }
1097
+ validateStreamAmount(val, originTotalAmount) {
1098
+ if (val.amountPerStep === 0n) {
1099
+ throw new InvalidInputError("Stream amount too small", "totalAmount", originTotalAmount);
1100
+ }
1101
+ if (val.cliffAmount > val.realTotalAmount) {
1102
+ throw new InvalidInputError("Invalid cliff settings");
1103
+ }
1104
+ }
1105
+ validateTimeline(val) {
1106
+ if (val.interval.toMillis() < MIN_INTERVAL_MS) {
1107
+ throw new InvalidInputError("Interval shall be at least 1 second", "interval", val.interval);
1108
+ }
1109
+ }
1110
+ };
1111
+ var CoinMetaHelper = class {
1112
+ constructor(suiClient) {
1113
+ this.suiClient = suiClient;
1114
+ this.coinMetaReg = /* @__PURE__ */ new Map();
1115
+ }
1116
+ coinMetaReg;
1117
+ async getCoinMeta(coinType) {
1118
+ const normalized = (0, import_utils5.normalizeStructTag)(coinType || import_utils5.SUI_TYPE_ARG);
1119
+ if (this.coinMetaReg.has(normalized)) {
1120
+ return this.coinMetaReg.get(normalized);
1121
+ }
1122
+ const meta = await this.queryCoinMeta(normalized);
1123
+ if (meta) {
1124
+ this.coinMetaReg.set(normalized, meta);
1125
+ }
1126
+ return meta;
1127
+ }
1128
+ async queryCoinMeta(coinType) {
1129
+ const res = await this.suiClient.getCoinMetadata({ coinType });
1130
+ return res || void 0;
1131
+ }
1132
+ };
1133
+
1134
+ // src/apps/mpay/stream/query.ts
1135
+ var import_utils8 = require("@mysten/sui.js/utils");
1136
+ var import_luxon4 = require("luxon");
1137
+
1138
+ // src/apps/mpay/stream/Stream.ts
1139
+ var import_transactions4 = require("@mysten/sui.js/transactions");
1140
+ var import_utils6 = require("@mysten/sui.js/utils");
1141
+ var import_luxon3 = require("luxon");
1142
+
1143
+ // src/apps/mpay/error/NotCreatorError.ts
1144
+ var NotCreatorError = class extends MPayError {
1145
+ constructor() {
1146
+ super(7 /* NotCreator */, "Connected wallet is not creator");
1147
+ }
1148
+ };
1149
+
1150
+ // src/apps/mpay/error/NotRecipientError.ts
1151
+ var NotRecipientError = class extends MPayError {
1152
+ constructor() {
1153
+ super(8 /* NotRecipient */, "Connected wallet is not recipient");
1154
+ }
1155
+ };
1156
+
1157
+ // src/apps/mpay/error/RpcError.ts
1158
+ var RpcError = class extends MPayError {
1159
+ constructor(msg, context) {
1160
+ super(6 /* RpcError */, msg, {
1161
+ context
1162
+ });
1163
+ }
1164
+ };
1165
+
1166
+ // src/apps/mpay/error/SanityError.ts
1167
+ var SanityError = class extends MPayError {
1168
+ constructor(msg, options = {}) {
1169
+ super(0 /* sanity */, msg, options);
1170
+ }
1171
+ };
1172
+
1173
+ // src/apps/mpay/error/StreamNotFoundError.ts
1174
+ var StreamNotFoundError = class extends MPayError {
1175
+ constructor(streamId) {
1176
+ super(5 /* StreamNotFound */, "Stream not found", {
1177
+ context: {
1178
+ streamId
1179
+ }
1180
+ });
1181
+ }
1182
+ };
1183
+
1184
+ // src/apps/mpay/utils/utils.ts
1185
+ var import_luxon2 = require("luxon");
1186
+ var MAX_U64 = (1n << 64n) - 1n;
1187
+ var TIME_ROUND_UNIT = 1e3;
1188
+ function roundDateTime(date) {
1189
+ let dateMs;
1190
+ if (typeof date === "number") {
1191
+ dateMs = date;
1192
+ } else if (typeof date === "bigint") {
1193
+ dateMs = Number(date);
1194
+ } else {
1195
+ dateMs = date.toMillis();
1196
+ }
1197
+ const roundMs = Math.round(dateMs / TIME_ROUND_UNIT);
1198
+ return import_luxon2.DateTime.fromMillis(roundMs * TIME_ROUND_UNIT);
1199
+ }
1200
+ function roundDuration(duration) {
1201
+ let durationMs;
1202
+ if (typeof duration === "number") {
1203
+ durationMs = duration;
1204
+ } else if (typeof duration === "bigint") {
1205
+ durationMs = Number(duration);
1206
+ } else {
1207
+ durationMs = duration.toMillis();
1208
+ }
1209
+ const roundMs = Math.round(durationMs / TIME_ROUND_UNIT);
1210
+ return import_luxon2.Duration.fromMillis(roundMs * TIME_ROUND_UNIT);
1211
+ }
1212
+
1213
+ // src/apps/mpay/stream/Stream.ts
1214
+ var Stream = class _Stream {
1215
+ constructor(globals, streamId, rawData) {
1216
+ this.globals = globals;
1217
+ this.streamId = streamId;
1218
+ this.rawData = rawData;
1219
+ this.streamContract = new StreamContract(globals.envConfig.contract, globals);
1220
+ }
1221
+ streamContract;
1222
+ type = "Stream";
1223
+ static async new(globals, streamId) {
1224
+ const rawData = await _Stream.fetchStreamData(globals, streamId);
1225
+ return new _Stream(globals, streamId, rawData);
1226
+ }
1227
+ static fromObjectData(globals, streamId, data) {
1228
+ const rawData = _Stream.parseRawStreamData(streamId, data);
1229
+ return new _Stream(globals, streamId, rawData);
1230
+ }
1231
+ get info() {
1232
+ return {
1233
+ name: this.name,
1234
+ creator: this.creator,
1235
+ coinType: this.coinType,
1236
+ totalAmount: this.totalAmount,
1237
+ start: this.timeStart,
1238
+ end: this.timeEnd,
1239
+ cancelable: this.cancelable,
1240
+ cliffAmount: this.cliff,
1241
+ duration: this.duration,
1242
+ interval: this.interval,
1243
+ steps: this.totalSteps,
1244
+ nextReleaseDate: this.nextReleaseDate,
1245
+ nextReleaseAmount: this.nextReleaseAmount,
1246
+ groupId: this.groupId,
1247
+ streamId: this.streamId,
1248
+ recipient: this.recipient,
1249
+ progress: this.progress,
1250
+ autoClaim: this.autoClaim
1251
+ };
1252
+ }
1253
+ get groupCommonInfo() {
1254
+ return {
1255
+ name: this.name,
1256
+ groupId: this.groupId,
1257
+ creator: this.creator,
1258
+ start: this.timeStart,
1259
+ interval: this.interval,
1260
+ steps: this.totalSteps,
1261
+ cancelable: this.cancelable
1262
+ };
1263
+ }
1264
+ async refresh() {
1265
+ this.rawData = await _Stream.fetchStreamData(this.globals, this.streamId);
1266
+ }
1267
+ refreshWithData(data) {
1268
+ if (data.data?.objectId !== this.streamId) {
1269
+ throw new SanityError("Object Id does not align");
1270
+ }
1271
+ this.rawData = _Stream.parseRawStreamData(this.streamId, data);
1272
+ }
1273
+ async historyEvents(pagination) {
1274
+ return this.globals.backend.getStreamHistory({
1275
+ streamId: this.streamId,
1276
+ pagination
1277
+ });
1278
+ }
1279
+ async cancel() {
1280
+ if (await this.globals.walletAddress() !== this.creator) {
1281
+ throw new NotCreatorError();
1282
+ }
1283
+ const txb = new import_transactions4.TransactionBlock();
1284
+ this.streamContract.cancelStream(txb, {
1285
+ streamId: this.streamId,
1286
+ coinType: this.coinType
1287
+ });
1288
+ return txb;
1289
+ }
1290
+ async claim() {
1291
+ if (await this.globals.walletAddress() !== this.recipient) {
1292
+ throw new NotRecipientError();
1293
+ }
1294
+ const txb = new import_transactions4.TransactionBlock();
1295
+ this.streamContract.claimStream(txb, {
1296
+ streamId: this.streamId,
1297
+ coinType: this.coinType
1298
+ });
1299
+ return txb;
1300
+ }
1301
+ async setAutoClaim(enabled) {
1302
+ if (await this.globals.walletAddress() !== this.recipient) {
1303
+ throw new NotRecipientError();
1304
+ }
1305
+ const txb = new import_transactions4.TransactionBlock();
1306
+ this.streamContract.setAutoClaim(txb, {
1307
+ streamId: this.streamId,
1308
+ coinType: this.coinType,
1309
+ enabled
1310
+ });
1311
+ return txb;
1312
+ }
1313
+ async claimByProxy() {
1314
+ const txb = new import_transactions4.TransactionBlock();
1315
+ this.streamContract.claimStreamByProxy(txb, {
1316
+ streamId: this.streamId,
1317
+ coinType: this.coinType
1318
+ });
1319
+ return txb;
1320
+ }
1321
+ get wallet() {
1322
+ return this.globals.wallet;
1323
+ }
1324
+ get client() {
1325
+ return this.globals.suiClient;
1326
+ }
1327
+ get coinType() {
1328
+ return (0, import_utils6.normalizeStructTag)(this.rawData.coinType);
1329
+ }
1330
+ get progress() {
1331
+ return {
1332
+ status: this.streamStatus,
1333
+ total: this.totalAmount,
1334
+ streamed: this.streamedAmount,
1335
+ claimed: this.claimedAmount,
1336
+ claimable: this.claimable,
1337
+ canceled: this.canceledAmount
1338
+ };
1339
+ }
1340
+ get balance() {
1341
+ return this.rawData.balance;
1342
+ }
1343
+ get autoClaim() {
1344
+ return this.rawData.autoClaim;
1345
+ }
1346
+ get amountPerEpoch() {
1347
+ return this.rawData.config.amountPerEpoch;
1348
+ }
1349
+ get cancelable() {
1350
+ return this.rawData.config.cancelable;
1351
+ }
1352
+ get cliff() {
1353
+ return this.rawData.config.cliff;
1354
+ }
1355
+ get creator() {
1356
+ return this.rawData.config.creator;
1357
+ }
1358
+ get interval() {
1359
+ return roundDuration(this.rawData.config.epochInterval);
1360
+ }
1361
+ get groupId() {
1362
+ const { metadata } = this.rawData.config;
1363
+ const md = decodeMetadata(metadata);
1364
+ return md.groupId;
1365
+ }
1366
+ get name() {
1367
+ const { metadata } = this.rawData.config;
1368
+ const md = decodeMetadata(metadata);
1369
+ return md.name;
1370
+ }
1371
+ get recipient() {
1372
+ return this.rawData.config.recipient;
1373
+ }
1374
+ get timeStart() {
1375
+ return roundDateTime(this.rawData.config.timeStart);
1376
+ }
1377
+ get duration() {
1378
+ const rawConfig = this.rawData.config;
1379
+ const duration = rawConfig.epochInterval * rawConfig.totalEpoch;
1380
+ return roundDuration(duration);
1381
+ }
1382
+ get timeEnd() {
1383
+ return this.timeStart.plus(this.duration);
1384
+ }
1385
+ get totalSteps() {
1386
+ return this.rawData.config.totalEpoch;
1387
+ }
1388
+ get claimable() {
1389
+ return this.streamedAmount - this.claimedAmount;
1390
+ }
1391
+ get nextReleaseDate() {
1392
+ if (this.currentEpoch === -1n) {
1393
+ return this.timeStart;
1394
+ }
1395
+ if (this.currentEpoch >= this.totalSteps || this.isCanceled) {
1396
+ return null;
1397
+ }
1398
+ return roundDateTime((this.currentEpoch + 1n) * this.rawData.config.epochInterval + this.rawData.config.timeStart);
1399
+ }
1400
+ get nextReleaseAmount() {
1401
+ if (this.currentEpoch === -1n) {
1402
+ return this.cliff;
1403
+ }
1404
+ if (this.currentEpoch >= this.totalSteps || this.isCanceled) {
1405
+ return null;
1406
+ }
1407
+ return this.amountPerEpoch;
1408
+ }
1409
+ get streamStatus() {
1410
+ const rawStatus = this.rawData.status.status;
1411
+ if (rawStatus === 16 /* CANCELED */) {
1412
+ return "CANCELED" /* CANCELED */;
1413
+ }
1414
+ if (rawStatus === 17 /* CANCELED_COMPLETED */) {
1415
+ return "SETTLED" /* SETTLED */;
1416
+ }
1417
+ if (rawStatus === 1 /* COMPLETED */) {
1418
+ return "COMPLETED" /* COMPLETED */;
1419
+ }
1420
+ if (this.currentEpoch >= this.totalSteps) {
1421
+ return "STREAMED" /* STREAMED */;
1422
+ }
1423
+ return "STREAMING" /* STREAMING */;
1424
+ }
1425
+ get streamedAmount() {
1426
+ if (this.currentEpoch === -1n) {
1427
+ return 0n;
1428
+ }
1429
+ if (this.isCanceled) {
1430
+ return this.rawData.status.epochCanceled * this.amountPerEpoch + this.cliff;
1431
+ }
1432
+ return this.currentEpoch * this.amountPerEpoch + this.cliff;
1433
+ }
1434
+ get claimedAmount() {
1435
+ if (this.rawData.status.epochClaimed === MAX_U64) {
1436
+ return 0n;
1437
+ }
1438
+ return this.rawData.status.epochClaimed * this.amountPerEpoch + this.cliff;
1439
+ }
1440
+ get currentEpoch() {
1441
+ const timeNowMs = import_luxon3.DateTime.now().toMillis();
1442
+ const timeStartMs = this.timeStart.toMillis();
1443
+ if (timeNowMs < timeStartMs) {
1444
+ return -1n;
1445
+ }
1446
+ const epoch = Math.floor((timeNowMs - timeStartMs) / Number(this.rawData.config.epochInterval));
1447
+ return BigInt(epoch) > Number(this.rawData.config.totalEpoch) ? this.rawData.config.totalEpoch : BigInt(epoch);
1448
+ }
1449
+ get totalAmount() {
1450
+ const rawConfig = this.rawData.config;
1451
+ return rawConfig.amountPerEpoch * rawConfig.totalEpoch + rawConfig.cliff;
1452
+ }
1453
+ get isCanceled() {
1454
+ const rawStatus = this.rawData.status.status;
1455
+ return rawStatus === 16 /* CANCELED */ || rawStatus === 17 /* CANCELED_COMPLETED */;
1456
+ }
1457
+ get canceledAmount() {
1458
+ return this.isCanceled ? this.totalAmount - this.streamedAmount : 0n;
1459
+ }
1460
+ static async fetchStreamData(globals, streamId) {
1461
+ const res = await globals.suiClient.getObject({
1462
+ id: streamId,
1463
+ options: {
1464
+ showContent: true,
1465
+ showType: true
1466
+ }
1467
+ });
1468
+ return _Stream.parseRawStreamData(streamId, res);
1469
+ }
1470
+ static parseRawStreamData(streamId, res) {
1471
+ if (res.error) {
1472
+ if (res.error.code === "notExists") {
1473
+ throw new StreamNotFoundError(streamId);
1474
+ }
1475
+ throw new RpcError(`get stream data: ${res.error.code}`, {
1476
+ streamId,
1477
+ ...res.error
1478
+ });
1479
+ }
1480
+ const content = res.data.content;
1481
+ if (content.dataType !== "moveObject") {
1482
+ throw new RpcError("Unexpected object type", {
1483
+ gotType: content.dataType
1484
+ });
1485
+ }
1486
+ const { typeParams } = (0, import_utils6.parseStructTag)(content.type);
1487
+ const coinType = (0, import_utils6.normalizeStructTag)(typeParams[0]);
1488
+ const dataFields = content.fields;
1489
+ const config = dataFields.config.fields;
1490
+ const status3 = dataFields.status.fields;
1491
+ return {
1492
+ coinType,
1493
+ autoClaim: dataFields.auto_claim,
1494
+ balance: BigInt(dataFields.balance.fields.balance),
1495
+ config: {
1496
+ amountPerEpoch: BigInt(config.amount_per_epoch),
1497
+ cancelable: config.cancelable,
1498
+ cliff: BigInt(config.cliff),
1499
+ creator: config.creator,
1500
+ epochInterval: BigInt(config.epoch_interval),
1501
+ metadata: config.metadata,
1502
+ recipient: config.recipient,
1503
+ timeStart: BigInt(config.time_start),
1504
+ totalEpoch: BigInt(config.total_epoch)
1505
+ },
1506
+ status: {
1507
+ status: status3.status,
1508
+ epochCanceled: BigInt(status3.epoch_canceled),
1509
+ epochClaimed: BigInt(status3.epoch_claimed)
1510
+ }
1511
+ };
1512
+ }
1513
+ };
1514
+
1515
+ // src/apps/mpay/error/InvalidStreamGroupError.ts
1516
+ var InvalidStreamGroupError = class extends MPayError {
1517
+ constructor(msg, context) {
1518
+ super(9 /* InvalidStreamGroup */, `Invalid stream group: ${msg}`, { context });
1519
+ }
1520
+ };
1521
+
1522
+ // src/apps/mpay/sui/iterator/iterator.ts
1523
+ async function getAllFromIterator(it) {
1524
+ const res = [];
1525
+ while (await it.hasNext()) {
1526
+ const val = await it.next();
1527
+ res.push(val);
1528
+ }
1529
+ if (res && Array.isArray(res[0])) {
1530
+ return res.flat(1);
1531
+ }
1532
+ return res;
1533
+ }
1534
+ var PagedIterator = class {
1535
+ constructor(requester) {
1536
+ this.requester = requester;
1537
+ this.curPage = void 0;
1538
+ this.init = true;
1539
+ }
1540
+ curPage;
1541
+ init;
1542
+ async hasNext() {
1543
+ if (this.init) {
1544
+ if (!this.curPage) {
1545
+ this.curPage = await this.requester.doNextRequest();
1546
+ }
1547
+ return !!this.curPage.data?.length || this.curPage.hasNext;
1548
+ }
1549
+ if (!this.curPage) {
1550
+ throw new Error("invalid implementation of iterator");
1551
+ }
1552
+ return this.curPage.hasNext;
1553
+ }
1554
+ async next() {
1555
+ if (this.init) {
1556
+ this.init = false;
1557
+ if (!this.curPage) {
1558
+ this.curPage = await this.requester.doNextRequest();
1559
+ }
1560
+ return this.curPage.data;
1561
+ }
1562
+ this.curPage = await this.requester.doNextRequest();
1563
+ return this.curPage.data;
1564
+ }
1565
+ };
1566
+ var EntryIterator = class {
1567
+ constructor(requester) {
1568
+ this.requester = requester;
1569
+ this.pager = new PagedIterator(requester);
1570
+ this.curData = [];
1571
+ this.cursor = 0;
1572
+ }
1573
+ cursor;
1574
+ pager;
1575
+ curData;
1576
+ async hasNext() {
1577
+ if (this.cursor < this.curData.length - 1) {
1578
+ return true;
1579
+ }
1580
+ return this.pager.hasNext();
1581
+ }
1582
+ async next() {
1583
+ this.cursor += 1;
1584
+ while (this.cursor >= this.curData.length) {
1585
+ if (!await this.pager.hasNext()) {
1586
+ throw new Error("not more data");
1587
+ } else {
1588
+ this.curData = await this.pager.next();
1589
+ this.cursor = 0;
1590
+ }
1591
+ }
1592
+ return this.curData[this.cursor];
1593
+ }
1594
+ };
1595
+
1596
+ // src/apps/mpay/sui/iterator/object.ts
1597
+ var REQUEST_PAGE_SIZE = 25;
1598
+ async function getObjectsById(suiClient, ids, options) {
1599
+ const oidIter = new ListOidIterator(ids);
1600
+ const iter = new ObjectBatchIterator(suiClient, oidIter, options);
1601
+ return await getAllFromIterator(iter);
1602
+ }
1603
+ var ListOidIterator = class {
1604
+ constructor(ids) {
1605
+ this.ids = ids;
1606
+ this.cursor = -1;
1607
+ }
1608
+ cursor;
1609
+ async hasNext() {
1610
+ return this.cursor < this.ids.length - 1;
1611
+ }
1612
+ async next() {
1613
+ this.cursor += 1;
1614
+ if (this.cursor >= this.ids.length) {
1615
+ throw new Error("invalid iterator implementation");
1616
+ }
1617
+ return this.ids[this.cursor];
1618
+ }
1619
+ };
1620
+ var ObjectBatchIterator = class extends EntryIterator {
1621
+ constructor(suiClient, idIter, options) {
1622
+ super(new ObjectBatchRequester(suiClient, idIter, options));
1623
+ this.suiClient = suiClient;
1624
+ this.idIter = idIter;
1625
+ this.options = options;
1626
+ }
1627
+ };
1628
+ var ObjectBatchRequester = class {
1629
+ constructor(suiClient, stringIter, options) {
1630
+ this.suiClient = suiClient;
1631
+ this.stringIter = stringIter;
1632
+ this.options = options;
1633
+ this.filter = options?.filter;
1634
+ this.pageSize = options?.pageSize || REQUEST_PAGE_SIZE;
1635
+ this.objectOptions = options?.objectOptions || {
1636
+ showType: true,
1637
+ showContent: true
1638
+ };
1639
+ }
1640
+ filter;
1641
+ pageSize;
1642
+ objectOptions;
1643
+ async doNextRequest() {
1644
+ const requestPage = [];
1645
+ while (requestPage.length < this.pageSize) {
1646
+ const hasNext = await this.stringIter.hasNext();
1647
+ if (!hasNext) {
1648
+ break;
1649
+ }
1650
+ const objId = await this.stringIter.next();
1651
+ if (objId) {
1652
+ requestPage.push(objId);
1653
+ }
1654
+ }
1655
+ const res = await this.suiClient.multiGetObjects({
1656
+ ids: requestPage,
1657
+ options: this.objectOptions
1658
+ });
1659
+ let filtered;
1660
+ if (this.filter) {
1661
+ const { filter } = this;
1662
+ filtered = res.filter((r) => filter?.(r));
1663
+ } else {
1664
+ filtered = res;
1665
+ }
1666
+ return {
1667
+ data: filtered,
1668
+ hasNext: await this.stringIter.hasNext()
1669
+ };
1670
+ }
1671
+ };
1672
+
1673
+ // src/apps/mpay/stream/StreamGroup.ts
1674
+ var StreamGroup = class _StreamGroup {
1675
+ constructor(globals, streams) {
1676
+ this.globals = globals;
1677
+ this.streams = streams;
1678
+ if (streams.length === 0) {
1679
+ throw new InvalidStreamGroupError("stream size 0");
1680
+ }
1681
+ const gids = streams.map((st) => st.groupId);
1682
+ const set = new Set(gids);
1683
+ if (set.size !== 1) {
1684
+ throw new InvalidInputError("Stream does not have same group ID");
1685
+ }
1686
+ }
1687
+ type = "StreamGroup";
1688
+ static async new(globals, ids) {
1689
+ const streamObjs = await getObjectsById(globals.suiClient, ids);
1690
+ streamObjs.forEach((obj) => {
1691
+ if (!obj) {
1692
+ throw new SanityError("stream group object data undefined");
1693
+ }
1694
+ });
1695
+ return _StreamGroup.newFromObjectResponse(globals, ids, streamObjs);
1696
+ }
1697
+ static async newFromObjectResponse(globals, ids, responses) {
1698
+ const streams = await _StreamGroup.parseGroupStreams(globals, ids, responses);
1699
+ return new _StreamGroup(globals, streams);
1700
+ }
1701
+ static checkStreamGroup(streams) {
1702
+ const commonInfos = streams.map((stream) => stream.groupCommonInfo);
1703
+ const expInfo = commonInfos[0];
1704
+ let isEqual = true;
1705
+ commonInfos.forEach((info) => {
1706
+ if (!isEqualStreamGroupCommonInfo(expInfo, info)) {
1707
+ isEqual = false;
1708
+ }
1709
+ });
1710
+ return isEqual;
1711
+ }
1712
+ async refresh() {
1713
+ const streamObjs = await getObjectsById(
1714
+ this.globals.suiClient,
1715
+ this.streams.map((stream) => stream.streamId)
1716
+ );
1717
+ this.streams.forEach((stream, i) => {
1718
+ stream.refreshWithData(streamObjs[i]);
1719
+ });
1720
+ }
1721
+ get groupId() {
1722
+ return this.streams[0].groupId;
1723
+ }
1724
+ get creator() {
1725
+ return this.streams[0].creator;
1726
+ }
1727
+ get info() {
1728
+ return {
1729
+ groupId: this.groupId,
1730
+ streamIds: this.streams.map((st) => st.streamId),
1731
+ progress: this.progress,
1732
+ name: this.streams[0].name,
1733
+ creator: this.creator,
1734
+ coinType: this.streams[0].coinType,
1735
+ totalAmount: this.streams.reduce((sum, st) => sum + st.totalAmount, 0n),
1736
+ start: this.streams[0].timeStart,
1737
+ end: this.streams[0].timeEnd,
1738
+ cancelable: this.streams[0].cancelable,
1739
+ cliffAmount: this.streams.reduce((sum, st) => sum + st.cliff, 0n),
1740
+ duration: this.streams[0].duration,
1741
+ interval: this.streams[0].interval,
1742
+ steps: this.streams[0].totalSteps,
1743
+ nextReleaseAmount: this.streams.reduce((sum, st) => {
1744
+ if (st.nextReleaseAmount === null) {
1745
+ return sum;
1746
+ }
1747
+ return sum + st.nextReleaseAmount;
1748
+ }, 0n),
1749
+ nextReleaseDate: this.streams[0].nextReleaseDate
1750
+ };
1751
+ }
1752
+ get progress() {
1753
+ return {
1754
+ total: this.streams.reduce((sum, st) => sum + st.totalAmount, 0n),
1755
+ streamed: this.streams.reduce((sum, st) => sum + st.streamedAmount, 0n),
1756
+ claimed: this.streams.reduce((sum, st) => sum + st.claimedAmount, 0n),
1757
+ claimable: this.streams.reduce((sum, st) => sum + st.claimable, 0n),
1758
+ canceled: this.streams.reduce((sum, st) => sum + st.canceledAmount, 0n)
1759
+ };
1760
+ }
1761
+ async historyEvents(pagination) {
1762
+ return this.globals.backend.getStreamHistory({
1763
+ groupId: this.groupId,
1764
+ pagination
1765
+ });
1766
+ }
1767
+ static async parseGroupStreams(globals, ids, responses) {
1768
+ const streams = responses.map((obj, i) => Stream.fromObjectData(globals, ids[i], obj)).filter((stream) => !!stream);
1769
+ if (new Set(streams.map((st) => st.groupId)).size !== 1) {
1770
+ throw new InvalidStreamGroupError("Not same group ID");
1771
+ }
1772
+ if (!this.checkStreamGroup(streams)) {
1773
+ throw new InvalidStreamGroupError("Not same stream settings");
1774
+ }
1775
+ return streams;
1776
+ }
1777
+ };
1778
+ function isEqualStreamGroupCommonInfo(info1, info2) {
1779
+ return info1.name === info2.name && info1.groupId === info2.groupId && info1.creator === info2.creator && info1.start.toMillis() === info2.start.toMillis() && info1.interval.toMillis() === info2.interval.toMillis() && info1.steps === info2.steps && info1.cancelable === info2.cancelable;
1780
+ }
1781
+
1782
+ // src/apps/mpay/stream/query.ts
1783
+ var PagedStreamListIterator = class _PagedStreamListIterator {
1784
+ constructor(it, pageSize) {
1785
+ this.it = it;
1786
+ this.pageSize = pageSize;
1787
+ }
1788
+ static async newIncoming(input) {
1789
+ const it = await StreamListIterator.newIncoming(input);
1790
+ return new _PagedStreamListIterator(it, input.pageSize);
1791
+ }
1792
+ static async newOutgoing(input) {
1793
+ const it = await StreamListIterator.newOutgoing(input);
1794
+ return new _PagedStreamListIterator(it, input.pageSize);
1795
+ }
1796
+ async hasNext() {
1797
+ return this.it.hasNext();
1798
+ }
1799
+ async next() {
1800
+ const res = [];
1801
+ while (res.length < this.pageSize && await this.it.hasNext()) {
1802
+ res.push(await this.it.next());
1803
+ }
1804
+ return res;
1805
+ }
1806
+ };
1807
+ var StreamListIterator = class _StreamListIterator {
1808
+ constructor(requester) {
1809
+ this.requester = requester;
1810
+ }
1811
+ cachedNext;
1812
+ static async newIncoming(input) {
1813
+ const requester = await StreamListRequester.newIncomingQuery(input);
1814
+ return new _StreamListIterator(requester);
1815
+ }
1816
+ static async newOutgoing(input) {
1817
+ const requester = await StreamListRequester.newOutgoingQuery(input);
1818
+ return new _StreamListIterator(requester);
1819
+ }
1820
+ async hasNext() {
1821
+ if (this.cachedNext === void 0) {
1822
+ this.cachedNext = await this.requester.doNextRequest();
1823
+ }
1824
+ return this.cachedNext !== null;
1825
+ }
1826
+ async next() {
1827
+ if (this.cachedNext === void 0) {
1828
+ const res2 = await this.requester.doNextRequest();
1829
+ if (res2 === null) {
1830
+ throw new SanityError("No more results");
1831
+ }
1832
+ return res2;
1833
+ }
1834
+ const res = this.cachedNext;
1835
+ this.cachedNext = void 0;
1836
+ if (res === null) {
1837
+ throw new SanityError("No more results");
1838
+ }
1839
+ return res;
1840
+ }
1841
+ };
1842
+ var StreamListRequester = class _StreamListRequester {
1843
+ constructor(globals, recipient, groupRefs, query) {
1844
+ this.globals = globals;
1845
+ this.recipient = recipient;
1846
+ this.groupRefs = groupRefs;
1847
+ this.query = query;
1848
+ this.current = 0;
1849
+ const oidIter = new ListOidIterator(groupRefs.flat().map((ref) => ref.streamId));
1850
+ this.objectIter = new ObjectBatchIterator(globals.suiClient, oidIter);
1851
+ }
1852
+ current = 0;
1853
+ objectIter;
1854
+ static async newIncomingQuery(input) {
1855
+ const backendQuery = convertToIncomingBackendQuery(input.query);
1856
+ const recipient = await input.globals.walletAddress();
1857
+ const refs = await input.globals.backend.getIncomingStreams(recipient, backendQuery);
1858
+ const filtered = refs.filter((ref) => (0, import_utils8.normalizeSuiAddress)(ref.recipient) === (0, import_utils8.normalizeSuiAddress)(recipient));
1859
+ const groupedRefs = groupAndSortRefs(filtered);
1860
+ return new _StreamListRequester(input.globals, recipient, groupedRefs, input.query);
1861
+ }
1862
+ static async newOutgoingQuery(input) {
1863
+ const backendQuery = convertToOutgoingBackendQuery(input.query);
1864
+ const sender = await input.globals.walletAddress();
1865
+ const refs = await input.globals.backend.getOutgoingStreams(sender, backendQuery);
1866
+ const groupedRefs = groupAndSortRefs(refs);
1867
+ return new _StreamListRequester(input.globals, sender, groupedRefs, input.query);
1868
+ }
1869
+ async doNextRequest() {
1870
+ if (this.current >= this.groupRefs.length) {
1871
+ return null;
1872
+ }
1873
+ const stRefs = this.groupRefs[this.current];
1874
+ if (stRefs.length === 1) {
1875
+ const stream = await getStreamFromIterator(this.globals, stRefs[0].streamId, this.objectIter);
1876
+ this.current++;
1877
+ return isStreamOfQuery(stream, this.query) ? stream : this.doNextRequest();
1878
+ }
1879
+ if (stRefs.length > 1) {
1880
+ const sg = await getStreamGroupFromIterator(
1881
+ this.globals,
1882
+ stRefs.map((ref) => ref.streamId),
1883
+ this.objectIter
1884
+ );
1885
+ this.current++;
1886
+ return isStreamGroupOfQuery(sg, this.query) ? sg : this.doNextRequest();
1887
+ }
1888
+ throw new SanityError("Stream group with no stream");
1889
+ }
1890
+ };
1891
+ function groupAndSortRefs(refs) {
1892
+ const m = /* @__PURE__ */ new Map();
1893
+ refs.forEach((ref) => {
1894
+ const groupList = m.get(ref.groupId);
1895
+ if (groupList) {
1896
+ groupList.push(ref);
1897
+ m.set(ref.groupId, groupList);
1898
+ } else {
1899
+ m.set(ref.groupId, [ref]);
1900
+ }
1901
+ });
1902
+ return Array.from(m.values()).sort(
1903
+ (gl1, gl2) => import_luxon4.DateTime.fromISO(gl2[0].createDate).toMillis() - import_luxon4.DateTime.fromISO(gl1[0].createDate).toMillis()
1904
+ );
1905
+ }
1906
+ function isStreamOfQuery(stream, query) {
1907
+ if (query === void 0) {
1908
+ return true;
1909
+ }
1910
+ const isStatus = isStreamOfStatus(stream, query.status);
1911
+ if (query && "claimable" in query && query.claimable !== void 0) {
1912
+ const isClaimable = query.claimable ? stream.progress.claimable !== 0n : stream.progress.claimable === 0n;
1913
+ return isStatus && isClaimable;
1914
+ }
1915
+ return isStatus;
1916
+ }
1917
+ function isStreamOfStatus(stream, filter) {
1918
+ if (filter === void 0) {
1919
+ return true;
1920
+ }
1921
+ if (!Array.isArray(filter)) {
1922
+ return stream.progress.status === filter;
1923
+ }
1924
+ return filter.includes(stream.progress.status);
1925
+ }
1926
+ function isStreamGroupOfQuery(sg, query) {
1927
+ if (!query) {
1928
+ return true;
1929
+ }
1930
+ let isStatus = false;
1931
+ sg.streams.forEach((stream) => {
1932
+ if (isStreamOfQuery(stream, query)) {
1933
+ isStatus = true;
1934
+ }
1935
+ });
1936
+ return isStatus;
1937
+ }
1938
+ async function getStreamFromIterator(globals, streamId, it) {
1939
+ const data = await getStreamObjectResponseFromIter(it, streamId);
1940
+ return Stream.fromObjectData(globals, streamId, data);
1941
+ }
1942
+ async function getStreamGroupFromIterator(globals, streamIds, it) {
1943
+ const objResponses = [];
1944
+ while (objResponses.length < streamIds.length) {
1945
+ const data = await getStreamObjectResponseFromIter(it, streamIds[objResponses.length]);
1946
+ objResponses.push(data);
1947
+ }
1948
+ return StreamGroup.newFromObjectResponse(globals, streamIds, objResponses);
1949
+ }
1950
+ async function getStreamObjectResponseFromIter(it, streamId) {
1951
+ if (!await it.hasNext()) {
1952
+ throw new SanityError("object iterator has been consumed");
1953
+ }
1954
+ const data = await it.next();
1955
+ if (!data || data.error || data.data === void 0 || data.data === null) {
1956
+ throw new SanityError(`object iterator undefined response`, {
1957
+ cause: data?.error
1958
+ });
1959
+ }
1960
+ if (data?.data?.objectId !== streamId) {
1961
+ throw new SanityError("stream id not aligned");
1962
+ }
1963
+ return data;
1964
+ }
1965
+ function convertToIncomingBackendQuery(query) {
1966
+ return {
1967
+ status: convertStreamStatus(query?.status),
1968
+ coinType: normalizeCoinTypeFilter(query?.coinType),
1969
+ sender: normalizeAddressFilter(query?.sender)
1970
+ };
1971
+ }
1972
+ function convertToOutgoingBackendQuery(query) {
1973
+ return {
1974
+ status: convertStreamStatus(query?.status),
1975
+ coinType: normalizeCoinTypeFilter(query?.coinType),
1976
+ recipient: normalizeAddressFilter(query?.recipient)
1977
+ };
1978
+ }
1979
+ function convertStreamStatus(status3) {
1980
+ if (status3 === void 0 || status3.length === 0) {
1981
+ return "all";
1982
+ }
1983
+ if (!Array.isArray(status3)) {
1984
+ return convertStreamStatusSingle(status3);
1985
+ }
1986
+ return status3.reduce((res, st) => {
1987
+ const sts = convertStreamStatus(st);
1988
+ if (!res) {
1989
+ return sts;
1990
+ }
1991
+ if (res === sts) {
1992
+ return sts;
1993
+ }
1994
+ return "all";
1995
+ }, void 0);
1996
+ }
1997
+ function convertStreamStatusSingle(status3) {
1998
+ switch (status3) {
1999
+ case "STREAMING":
2000
+ case "STREAMED":
2001
+ case "CANCELED":
2002
+ return "active";
2003
+ case "COMPLETED":
2004
+ case "SETTLED":
2005
+ return "inactive";
2006
+ default:
2007
+ throw new InvalidInputError("Unknown stream filtered status");
2008
+ }
2009
+ }
2010
+ function normalizeCoinTypeFilter(coinType) {
2011
+ if (!coinType) {
2012
+ return void 0;
2013
+ }
2014
+ if (!Array.isArray(coinType)) {
2015
+ return (0, import_utils8.normalizeStructTag)(coinType);
2016
+ }
2017
+ return coinType.length !== 0 ? coinType.map((ct) => (0, import_utils8.normalizeStructTag)(ct)) : void 0;
2018
+ }
2019
+ function normalizeAddressFilter(address) {
2020
+ if (!address) {
2021
+ return void 0;
2022
+ }
2023
+ if (!Array.isArray(address)) {
2024
+ return (0, import_utils8.normalizeSuiAddress)(address);
2025
+ }
2026
+ return address.length !== 0 ? address.map((addr) => (0, import_utils8.normalizeSuiAddress)(addr)) : void 0;
2027
+ }
2028
+
2029
+ // src/apps/mpay/stream/client.ts
2030
+ var MSafeAccountAdapter = class {
2031
+ constructor(msafe) {
2032
+ this.msafe = msafe;
2033
+ }
2034
+ get type() {
2035
+ return "msafe" /* msafe */;
2036
+ }
2037
+ async address() {
2038
+ return this.msafe.address();
2039
+ }
2040
+ async requestCoins(reqs) {
2041
+ return this.msafe.requestCoins(reqs);
2042
+ }
2043
+ };
2044
+ var MPayClient = class {
2045
+ globals;
2046
+ helper;
2047
+ constructor(env, options) {
2048
+ this.globals = Globals.new(env, options);
2049
+ this.helper = new MPayHelper(this.globals);
2050
+ }
2051
+ connectMSafeAccount(msafe) {
2052
+ const adapter = new MSafeAccountAdapter(msafe);
2053
+ this.globals.connectWallet(adapter);
2054
+ }
2055
+ async createStream(info) {
2056
+ return this.builder().createStreams(info);
2057
+ }
2058
+ async getStream(streamId) {
2059
+ return Stream.new(this.globals, streamId);
2060
+ }
2061
+ async getIncomingStreams(query, pageSize = 10) {
2062
+ return PagedStreamListIterator.newIncoming({
2063
+ globals: this.globals,
2064
+ query,
2065
+ pageSize
2066
+ });
2067
+ }
2068
+ async getOutgoingStreams(query, pageSize = 10) {
2069
+ return PagedStreamListIterator.newOutgoing({
2070
+ globals: this.globals,
2071
+ query,
2072
+ pageSize
2073
+ });
2074
+ }
2075
+ async getCoinTypesForStreamFilter() {
2076
+ const address = await this.wallet.address();
2077
+ const coinTypes = await this.globals.backend.getAllCoinTypes(address);
2078
+ return coinTypes.map((coinType) => (0, import_utils9.normalizeStructTag)(coinType));
2079
+ }
2080
+ async getRecipientsForStreamFilter(options) {
2081
+ const address = await this.wallet.address();
2082
+ const recipients = await this.globals.backend.getAllRecipients(address, options);
2083
+ return recipients.map((recipient) => (0, import_utils9.normalizeSuiAddress)(recipient));
2084
+ }
2085
+ async getCreatorsForStreamFilter(options) {
2086
+ const address = await this.wallet.address();
2087
+ const creators = await this.globals.backend.getAllSenders(address, options);
2088
+ return creators.map((creator) => (0, import_utils9.normalizeSuiAddress)(creator));
2089
+ }
2090
+ get wallet() {
2091
+ return this.globals.wallet;
2092
+ }
2093
+ builder() {
2094
+ return new MPayBuilder(this.globals);
2095
+ }
2096
+ };
2097
+
2098
+ // src/apps/mpay/create-stream.ts
2099
+ var CreateStreamIntention = class _CreateStreamIntention extends CoreBaseIntention {
2100
+ constructor(data) {
2101
+ super(data);
2102
+ this.data = data;
2103
+ }
2104
+ txType;
2105
+ txSubType;
2106
+ async build(input) {
2107
+ const { network } = input;
2108
+ const mpayClient = new MPayClient(network === "sui:mainnet" ? "prod" /* prod */ : "dev" /* dev */);
2109
+ const txb = await mpayClient.createStream(this.data);
2110
+ return txb;
2111
+ }
2112
+ static fromData(data) {
2113
+ return new _CreateStreamIntention(data);
2114
+ }
2115
+ };
2116
+
2117
+ // src/apps/mpay/decoder/create.ts
2118
+ var import_utils11 = require("@mysten/sui.js/utils");
2119
+
2120
+ // src/apps/mpay/decoder/moveCall.ts
2121
+ var import_bcs2 = require("@mysten/sui.js/bcs");
2122
+ var import_utils10 = require("@mysten/sui.js/utils");
2123
+ var MoveCallHelper = class _MoveCallHelper {
2124
+ constructor(moveCall, txb) {
2125
+ this.moveCall = moveCall;
2126
+ this.txb = txb;
2127
+ }
2128
+ decodeSharedObjectId(argIndex) {
2129
+ const input = this.getInputParam(argIndex);
2130
+ return _MoveCallHelper.getSharedObjectId(input);
2131
+ }
2132
+ decodeOwnedObjectId(argIndex) {
2133
+ const input = this.getInputParam(argIndex);
2134
+ return _MoveCallHelper.getOwnedObjectId(input);
2135
+ }
2136
+ decodeInputU64(argIndex) {
2137
+ const strVal = this.decodePureArg(argIndex, "u64");
2138
+ return BigInt(strVal);
2139
+ }
2140
+ decodeInputAddress(argIndex) {
2141
+ const input = this.decodePureArg(argIndex, "address");
2142
+ return (0, import_utils10.normalizeSuiAddress)(input);
2143
+ }
2144
+ decodeInputString(argIndex) {
2145
+ return this.decodePureArg(argIndex, "string");
2146
+ }
2147
+ decodeInputBool(argIndex) {
2148
+ return this.decodePureArg(argIndex, "bool");
2149
+ }
2150
+ decodePureArg(argIndex, bcsType) {
2151
+ const input = this.getInputParam(argIndex);
2152
+ return _MoveCallHelper.getPureInputValue(input, bcsType);
2153
+ }
2154
+ getInputParam(argIndex) {
2155
+ const arg = this.moveCall.arguments[argIndex];
2156
+ if (arg.kind !== "Input") {
2157
+ throw new Error("not input type");
2158
+ }
2159
+ return this.txb.blockData.inputs[arg.index];
2160
+ }
2161
+ static getPureInputValue(input, bcsType) {
2162
+ if (input.type !== "pure") {
2163
+ throw new Error("not pure argument");
2164
+ }
2165
+ if (typeof input.value === "object" && "Pure" in input.value) {
2166
+ const bcsNums = input.value.Pure;
2167
+ return import_bcs2.bcs.de(bcsType, new Uint8Array(bcsNums));
2168
+ }
2169
+ return input.value;
2170
+ }
2171
+ static getOwnedObjectId(input) {
2172
+ if (input.type !== "object") {
2173
+ throw new Error(`not object argument: ${JSON.stringify(input)}`);
2174
+ }
2175
+ if (typeof input.value === "object") {
2176
+ if (!("Object" in input.value) || !("ImmOrOwned" in input.value.Object)) {
2177
+ throw new Error("not ImmOrOwned");
2178
+ }
2179
+ return (0, import_utils10.normalizeSuiAddress)(input.value.Object.ImmOrOwned.objectId);
2180
+ }
2181
+ return (0, import_utils10.normalizeSuiAddress)(input.value);
2182
+ }
2183
+ static getSharedObjectId(input) {
2184
+ if (input.type !== "object") {
2185
+ throw new Error(`not object argument: ${JSON.stringify(input)}`);
2186
+ }
2187
+ if (typeof input.value !== "object") {
2188
+ return (0, import_utils10.normalizeSuiAddress)(input.value);
2189
+ }
2190
+ if (!("Object" in input.value) || !("Shared" in input.value.Object)) {
2191
+ throw new Error("not Shared");
2192
+ }
2193
+ return (0, import_utils10.normalizeSuiAddress)(input.value.Object.Shared.objectId);
2194
+ }
2195
+ static getPureInput(input, bcsType) {
2196
+ if (input.type !== "pure") {
2197
+ throw new Error("not pure argument");
2198
+ }
2199
+ if (typeof input.value !== "object") {
2200
+ return input.value;
2201
+ }
2202
+ if (!("Pure" in input.value)) {
2203
+ throw new Error("Pure not in value");
2204
+ }
2205
+ const bcsVal = input.value.Pure;
2206
+ return import_bcs2.bcs.de(bcsType, new Uint8Array(bcsVal));
2207
+ }
2208
+ typeArg(index) {
2209
+ return (0, import_utils10.normalizeStructTag)(this.moveCall.typeArguments[index]);
2210
+ }
2211
+ txArg(index) {
2212
+ return this.moveCall.arguments[index];
2213
+ }
2214
+ };
2215
+
2216
+ // src/apps/mpay/decoder/create.ts
2217
+ var CreateStreamDecodeHelper = class {
2218
+ constructor(globals, txb) {
2219
+ this.globals = globals;
2220
+ this.txb = txb;
2221
+ }
2222
+ decode() {
2223
+ const streamInfo = this.decodeCreateStreamInfo();
2224
+ const fees = this.createStreamHelper().calculateCreateStreamFees(streamInfo);
2225
+ const coinMerges = this.getCoinMerges();
2226
+ return {
2227
+ type: "CreateStream" /* CREATE_STREAM */,
2228
+ info: streamInfo,
2229
+ fees,
2230
+ coinMerges
2231
+ };
2232
+ }
2233
+ decodeCreateStreamInfo() {
2234
+ const moveCalls = this.createStreamTransactions();
2235
+ const infos = moveCalls.map((moveCall) => this.getCreationInfoFromMoveCall(moveCall));
2236
+ return this.aggregateGroupStreamInfo(infos);
2237
+ }
2238
+ createStreamTransactions() {
2239
+ const txs = this.transactions.filter(
2240
+ (tx) => tx.kind === "MoveCall" && isSameTarget(tx.target, this.contract.createStreamTarget)
2241
+ );
2242
+ if (txs.length === 0) {
2243
+ throw new SanityError("No create stream transactions");
2244
+ }
2245
+ return txs.map((tx) => new MoveCallHelper(tx, this.txb));
2246
+ }
2247
+ getCreationInfoFromMoveCall(moveCall) {
2248
+ const metadata = moveCall.decodeInputString(4);
2249
+ const { name, groupId } = decodeMetadata(metadata);
2250
+ const recipient = moveCall.decodeInputAddress(5);
2251
+ const timeStart = moveCall.decodeInputU64(6);
2252
+ const cliff = moveCall.decodeInputU64(7);
2253
+ const epochInterval = moveCall.decodeInputU64(8);
2254
+ const totalEpoch = moveCall.decodeInputU64(9);
2255
+ const amountPerEpoch = moveCall.decodeInputU64(10);
2256
+ const cancelable = moveCall.decodeInputBool(11);
2257
+ const coinType = moveCall.typeArg(0);
2258
+ return {
2259
+ name,
2260
+ groupId,
2261
+ recipient,
2262
+ timeStart,
2263
+ cliff,
2264
+ epochInterval,
2265
+ totalEpoch,
2266
+ amountPerEpoch,
2267
+ cancelable,
2268
+ coinType
2269
+ };
2270
+ }
2271
+ aggregateGroupStreamInfo(infos) {
2272
+ const commonInfoSet = new Set(
2273
+ infos.map(
2274
+ (info) => JSON.stringify({
2275
+ name: info.name,
2276
+ groupId: info.groupId,
2277
+ timeStart: String(info.timeStart),
2278
+ epochInterval: String(info.epochInterval),
2279
+ totalEpoch: String(info.totalEpoch),
2280
+ cancelable: info.cancelable,
2281
+ coinType: info.coinType
2282
+ })
2283
+ )
2284
+ );
2285
+ if (commonInfoSet.size !== 1) {
2286
+ throw new InvalidInputError("Stream group not have common info");
2287
+ }
2288
+ const recipients = infos.map((info) => ({
2289
+ address: info.recipient,
2290
+ amountPerStep: info.amountPerEpoch,
2291
+ cliffAmount: info.cliff
2292
+ }));
2293
+ return {
2294
+ name: infos[0].name,
2295
+ coinType: infos[0].coinType,
2296
+ recipients,
2297
+ interval: infos[0].epochInterval,
2298
+ steps: infos[0].totalEpoch,
2299
+ startTimeMs: infos[0].timeStart,
2300
+ cancelable: infos[0].cancelable
2301
+ };
2302
+ }
2303
+ getCoinMerges() {
2304
+ const createStreamTx = this.createStreamTransactions()[0];
2305
+ return this.getCoinMergeForCreateStream(createStreamTx);
2306
+ }
2307
+ getCoinMergeForCreateStream(moveCall) {
2308
+ const coinType = moveCall.typeArg(0);
2309
+ const paymentCoin = moveCall.txArg(2);
2310
+ const paymentCoinMerge = this.getCoinMergeFromNestedResult(paymentCoin, coinType, moveCall);
2311
+ if (coinType === (0, import_utils11.normalizeStructTag)(import_utils11.SUI_TYPE_ARG)) {
2312
+ return [paymentCoinMerge];
2313
+ }
2314
+ const flatFeeCoin = moveCall.txArg(3);
2315
+ const flatCoinMerge = this.getCoinMergeFromNestedResult(flatFeeCoin, (0, import_utils11.normalizeStructTag)(import_utils11.SUI_TYPE_ARG), moveCall);
2316
+ return [paymentCoinMerge, flatCoinMerge];
2317
+ }
2318
+ getCoinMergeFromNestedResult(coinArg, coinType, moveCall) {
2319
+ if (coinArg.kind === "GasCoin") {
2320
+ return {
2321
+ primary: "GAS",
2322
+ coinType
2323
+ };
2324
+ }
2325
+ if (coinArg.kind === "Input") {
2326
+ const arg = this.getInputArg(coinArg);
2327
+ const objectId = MoveCallHelper.getOwnedObjectId(arg);
2328
+ const mergeTx = this.transactions.find((tx) => {
2329
+ if (tx.kind !== "MergeCoins") {
2330
+ return false;
2331
+ }
2332
+ if (tx.destination.kind !== "Input") {
2333
+ throw new Error("merge coin destination not Input type");
2334
+ }
2335
+ const primaryCoinInput = this.getInputArg(tx.destination);
2336
+ return MoveCallHelper.getOwnedObjectId(primaryCoinInput) === objectId;
2337
+ });
2338
+ if (!mergeTx) {
2339
+ return {
2340
+ primary: objectId,
2341
+ coinType
2342
+ };
2343
+ }
2344
+ return {
2345
+ primary: objectId,
2346
+ merged: mergeTx.sources.map((sourceArg) => {
2347
+ const sourceInputArg = this.getInputArg(sourceArg);
2348
+ return MoveCallHelper.getOwnedObjectId(sourceInputArg);
2349
+ }),
2350
+ coinType
2351
+ };
2352
+ }
2353
+ if (coinArg.kind === "NestedResult") {
2354
+ const parentTx = this.transactions[coinArg.index];
2355
+ if (parentTx.kind !== "SplitCoins") {
2356
+ throw new InvalidInputError(`Transaction type not expected. Expect SplitCoins, got ${parentTx.kind}`);
2357
+ }
2358
+ return this.getCoinMergeFromNestedResult(parentTx.coin, coinType, moveCall);
2359
+ }
2360
+ if (coinArg.kind === "Result") {
2361
+ throw new Error("Result type not expected for coin inputs");
2362
+ }
2363
+ throw new Error(`Unknown argument kind`);
2364
+ }
2365
+ mergeCoinTransactions() {
2366
+ return this.transactions.filter((tx) => tx.kind === "MergeCoins");
2367
+ }
2368
+ get transactions() {
2369
+ return this.txb.blockData.transactions;
2370
+ }
2371
+ get contract() {
2372
+ return new StreamContract(this.globals.envConfig.contract, this.globals);
2373
+ }
2374
+ get feeContract() {
2375
+ return new FeeContract(this.globals.envConfig.contract, this.globals);
2376
+ }
2377
+ createStreamHelper() {
2378
+ return new CreateStreamHelper(this.globals, this.feeContract, this.contract);
2379
+ }
2380
+ getInputArg(arg) {
2381
+ if (arg.kind !== "Input") {
2382
+ throw new Error("not input type");
2383
+ }
2384
+ return "value" in arg ? arg : this.txb.blockData.inputs[arg.index];
2385
+ }
2386
+ };
2387
+
2388
+ // src/apps/mpay/decoder/decoder.ts
2389
+ var DecodeHelper = class {
2390
+ constructor(globals, txb) {
2391
+ this.globals = globals;
2392
+ this.txb = txb;
2393
+ this.contract = new StreamContract(globals.envConfig.contract, globals);
2394
+ }
2395
+ contract;
2396
+ decode() {
2397
+ if (this.isCreateStreamTransaction()) {
2398
+ return this.decodeCreateStreamTransaction();
2399
+ }
2400
+ if (this.isClaimByProxyTransaction()) {
2401
+ return this.decodeClaimByProxyTransaction();
2402
+ }
2403
+ if (this.isSetAutoClaimTransaction()) {
2404
+ return this.decodeSetAutoClaimTransaction();
2405
+ }
2406
+ if (this.isCancelStreamTransaction()) {
2407
+ return this.decodeCancelStreamTransaction();
2408
+ }
2409
+ if (this.isClaimStreamTransaction()) {
2410
+ return this.decodeClaimTransaction();
2411
+ }
2412
+ return void 0;
2413
+ }
2414
+ get transactions() {
2415
+ return this.txb.blockData.transactions;
2416
+ }
2417
+ isCreateStreamTransaction() {
2418
+ const createStreamIndex = this.transactions.findIndex(
2419
+ (tx) => tx.kind === "MoveCall" && isSameTarget(tx.target, this.contract.createStreamTarget)
2420
+ );
2421
+ return createStreamIndex !== -1;
2422
+ }
2423
+ isSetAutoClaimTransaction() {
2424
+ return this.transactions.length === 1 && this.transactions[0].kind === "MoveCall" && isSameTarget(this.transactions[0].target, this.contract.setAutoClaimTarget);
2425
+ }
2426
+ isCancelStreamTransaction() {
2427
+ return this.transactions.length === 1 && this.transactions[0].kind === "MoveCall" && isSameTarget(this.transactions[0].target, this.contract.cancelStreamTarget);
2428
+ }
2429
+ isClaimStreamTransaction() {
2430
+ return this.transactions.length === 1 && this.transactions[0].kind === "MoveCall" && isSameTarget(this.transactions[0].target, this.contract.claimStreamTarget);
2431
+ }
2432
+ isClaimByProxyTransaction() {
2433
+ return this.transactions.length === 1 && this.transactions[0].kind === "MoveCall" && isSameTarget(this.transactions[0].target, this.contract.claimStreamByProxyTarget);
2434
+ }
2435
+ decodeCreateStreamTransaction() {
2436
+ const helper = new CreateStreamDecodeHelper(this.globals, this.txb);
2437
+ return helper.decode();
2438
+ }
2439
+ decodeSetAutoClaimTransaction() {
2440
+ const streamId = this.helper.decodeSharedObjectId(0);
2441
+ const enabled = this.helper.decodeInputBool(1);
2442
+ return {
2443
+ type: "SetAutoClaim" /* SET_AUTO_CLAIM */,
2444
+ streamId,
2445
+ enabled
2446
+ };
2447
+ }
2448
+ decodeClaimTransaction() {
2449
+ const streamId = this.helper.decodeSharedObjectId(0);
2450
+ return {
2451
+ type: "Claim" /* CLAIM */,
2452
+ streamId
2453
+ };
2454
+ }
2455
+ decodeClaimByProxyTransaction() {
2456
+ const streamId = this.helper.decodeSharedObjectId(0);
2457
+ return {
2458
+ type: "ClaimByProxy" /* CLAIM_BY_PROXY */,
2459
+ streamId
2460
+ };
2461
+ }
2462
+ decodeCancelStreamTransaction() {
2463
+ const streamId = this.helper.decodeSharedObjectId(0);
2464
+ return {
2465
+ type: "Cancel" /* CANCEL */,
2466
+ streamId
2467
+ };
2468
+ }
2469
+ get helper() {
2470
+ const moveCall = this.transactions[0];
2471
+ return new MoveCallHelper(moveCall, this.txb);
2472
+ }
2473
+ };
2474
+
2475
+ // src/apps/mpay/helper.ts
2476
+ var MPayAppHelper = class {
2477
+ application = "mpay";
2478
+ deserialize(input) {
2479
+ const { chain, transactionBlock } = input;
2480
+ const globals = Globals.new(chain === "sui:mainnet" ? "prod" /* prod */ : "dev" /* dev */);
2481
+ const decoder = new DecodeHelper(globals, transactionBlock);
2482
+ const result = decoder.decode();
2483
+ console.log("\u{1F680} ~ MPayHelper ~ deserialize ~ input:", input, result);
2484
+ if (result.type === "CreateStream" /* CREATE_STREAM */) {
2485
+ return {
2486
+ txType: import_sui3_utils.TransactionType.Other,
2487
+ txSubType: import_sui3_utils.StreamEventType.Create,
2488
+ intentionData: result.info
2489
+ };
2490
+ }
2491
+ throw new Error(`Unknown transaction type: ${result.type}`);
2492
+ }
2493
+ async build(input) {
2494
+ const { network, intentionData, suiClient, account } = input;
2495
+ let intention;
2496
+ switch (input.txSubType) {
2497
+ case import_sui3_utils.StreamEventType.Create:
2498
+ intention = CreateStreamIntention.fromData(intentionData);
2499
+ break;
2500
+ default:
2501
+ throw new Error("not implemented");
2502
+ }
2503
+ return intention.build({ network, suiClient, account });
2504
+ }
2505
+ };
2506
+
2507
+ // src/apps/msafe-core/helper.ts
2508
+ var import_sui3_utils5 = require("@msafe/sui3-utils");
2509
+
57
2510
  // src/apps/msafe-core/coin-transfer.ts
2511
+ var import_sui3_utils2 = require("@msafe/sui3-utils");
58
2512
  var CoinTransferIntention = class _CoinTransferIntention extends CoreBaseIntention {
59
2513
  constructor(data) {
60
2514
  super(data);
@@ -64,7 +2518,7 @@ var CoinTransferIntention = class _CoinTransferIntention extends CoreBaseIntenti
64
2518
  txSubType;
65
2519
  async build(input) {
66
2520
  const { suiClient, account } = input;
67
- return (0, import_sui3_utils.buildCoinTransferTxb)(suiClient, this.data, account.address);
2521
+ return (0, import_sui3_utils2.buildCoinTransferTxb)(suiClient, this.data, account.address);
68
2522
  }
69
2523
  static fromData(data) {
70
2524
  return new _CoinTransferIntention(data);
@@ -72,7 +2526,7 @@ var CoinTransferIntention = class _CoinTransferIntention extends CoreBaseIntenti
72
2526
  };
73
2527
 
74
2528
  // src/apps/msafe-core/object-transfer.ts
75
- var import_sui3_utils2 = require("@msafe/sui3-utils");
2529
+ var import_sui3_utils3 = require("@msafe/sui3-utils");
76
2530
  var ObjectTransferIntention = class _ObjectTransferIntention extends CoreBaseIntention {
77
2531
  constructor(data) {
78
2532
  super(data);
@@ -82,7 +2536,7 @@ var ObjectTransferIntention = class _ObjectTransferIntention extends CoreBaseInt
82
2536
  txSubType;
83
2537
  async build(input) {
84
2538
  const { suiClient, account } = input;
85
- return (0, import_sui3_utils2.buildObjectTransferTxb)(suiClient, this.data, account.address);
2539
+ return (0, import_sui3_utils3.buildObjectTransferTxb)(suiClient, this.data, account.address);
86
2540
  }
87
2541
  static fromData(data) {
88
2542
  return new _ObjectTransferIntention(data);
@@ -90,8 +2544,8 @@ var ObjectTransferIntention = class _ObjectTransferIntention extends CoreBaseInt
90
2544
  };
91
2545
 
92
2546
  // src/apps/msafe-core/plain-payload.ts
93
- var import_sui3_utils3 = require("@msafe/sui3-utils");
94
- var import_transactions = require("@mysten/sui.js/transactions");
2547
+ var import_sui3_utils4 = require("@msafe/sui3-utils");
2548
+ var import_transactions5 = require("@mysten/sui.js/transactions");
95
2549
  var PlainPayloadIntention = class _PlainPayloadIntention extends CoreBaseIntention {
96
2550
  constructor(data) {
97
2551
  super(data);
@@ -101,8 +2555,8 @@ var PlainPayloadIntention = class _PlainPayloadIntention extends CoreBaseIntenti
101
2555
  txSubType;
102
2556
  async build(input) {
103
2557
  const { account } = input;
104
- const tb = import_transactions.TransactionBlock.from(this.data.content);
105
- if (!(0, import_sui3_utils3.isSameAddress)(tb.blockData.sender, account.address)) {
2558
+ const tb = import_transactions5.TransactionBlock.from(this.data.content);
2559
+ if (!(0, import_sui3_utils4.isSameAddress)(tb.blockData.sender, account.address)) {
106
2560
  throw new Error("Invalid sender address");
107
2561
  }
108
2562
  return tb;
@@ -116,7 +2570,7 @@ var PlainPayloadIntention = class _PlainPayloadIntention extends CoreBaseIntenti
116
2570
  var CoreHelper = class {
117
2571
  application;
118
2572
  constructor() {
119
- this.application = import_sui3_utils4.TransactionDefaultApplication;
2573
+ this.application = import_sui3_utils5.TransactionDefaultApplication;
120
2574
  }
121
2575
  deserialize() {
122
2576
  throw new Error("MSafe core transaction intention should be build from API");
@@ -125,13 +2579,13 @@ var CoreHelper = class {
125
2579
  const { suiClient, account } = input;
126
2580
  let intention;
127
2581
  switch (input.txSubType) {
128
- case import_sui3_utils4.TransactionSubTypes.assets.coin.send:
2582
+ case import_sui3_utils5.TransactionSubTypes.assets.coin.send:
129
2583
  intention = CoinTransferIntention.fromData(input.intentionData);
130
2584
  break;
131
- case import_sui3_utils4.TransactionSubTypes.assets.object.send:
2585
+ case import_sui3_utils5.TransactionSubTypes.assets.object.send:
132
2586
  intention = ObjectTransferIntention.fromData(input.intentionData);
133
2587
  break;
134
- case import_sui3_utils4.TransactionSubTypes.others.plain:
2588
+ case import_sui3_utils5.TransactionSubTypes.others.plain:
135
2589
  intention = PlainPayloadIntention.fromData(input.intentionData);
136
2590
  break;
137
2591
  default:
@@ -163,7 +2617,7 @@ var MSafeApps = class {
163
2617
  };
164
2618
 
165
2619
  // src/index.ts
166
- var appHelpers = new MSafeApps([new CoreHelper()]);
2620
+ var appHelpers = new MSafeApps([new CoreHelper(), new MPayAppHelper()]);
167
2621
  // Annotate the CommonJS export names for ESM import in node:
168
2622
  0 && (module.exports = {
169
2623
  appHelpers