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