@portal-hq/web 3.17.0 → 3.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/lib/commonjs/index.js +62 -20
  2. package/lib/commonjs/index.test.js +51 -10
  3. package/lib/commonjs/integrations/ramps/index.js +2 -0
  4. package/lib/commonjs/integrations/ramps/meld/index.js +121 -0
  5. package/lib/commonjs/integrations/ramps/meld/index.test.js +162 -0
  6. package/lib/commonjs/integrations/ramps/noah/index.js +2 -2
  7. package/lib/commonjs/integrations/ramps/noah/index.test.js +11 -2
  8. package/lib/commonjs/mpc/index.js +199 -3
  9. package/lib/commonjs/mpc/index.test.js +634 -0
  10. package/lib/commonjs/provider/index.js +44 -2
  11. package/lib/commonjs/provider/index.test.js +186 -0
  12. package/lib/commonjs/rpc.test.js +162 -0
  13. package/lib/commonjs/shared/rpc/auth.js +29 -0
  14. package/lib/commonjs/shared/rpc/defaults.js +40 -0
  15. package/lib/commonjs/shared/types/index.js +1 -0
  16. package/lib/commonjs/shared/types/meld.js +2 -0
  17. package/lib/esm/index.js +59 -19
  18. package/lib/esm/index.test.js +51 -10
  19. package/lib/esm/integrations/ramps/index.js +2 -0
  20. package/lib/esm/integrations/ramps/meld/index.js +118 -0
  21. package/lib/esm/integrations/ramps/meld/index.test.js +157 -0
  22. package/lib/esm/integrations/ramps/noah/index.js +2 -2
  23. package/lib/esm/integrations/ramps/noah/index.test.js +11 -2
  24. package/lib/esm/mpc/index.js +199 -3
  25. package/lib/esm/mpc/index.test.js +635 -1
  26. package/lib/esm/provider/index.js +44 -2
  27. package/lib/esm/provider/index.test.js +186 -0
  28. package/lib/esm/rpc.test.js +157 -0
  29. package/lib/esm/shared/rpc/auth.js +25 -0
  30. package/lib/esm/shared/rpc/defaults.js +36 -0
  31. package/lib/esm/shared/types/index.js +1 -0
  32. package/lib/esm/shared/types/meld.js +1 -0
  33. package/noah-types.d.ts +17 -1
  34. package/package.json +1 -1
  35. package/src/__mocks/constants.ts +68 -0
  36. package/src/__mocks/portal/portal.ts +0 -1
  37. package/src/index.test.ts +90 -0
  38. package/src/index.ts +159 -7
  39. package/src/integrations/ramps/index.ts +3 -0
  40. package/src/integrations/ramps/meld/index.test.ts +189 -0
  41. package/src/integrations/ramps/meld/index.ts +149 -0
  42. package/src/integrations/ramps/noah/index.test.ts +11 -2
  43. package/src/integrations/ramps/noah/index.ts +5 -2
  44. package/src/mpc/index.test.ts +804 -7
  45. package/src/mpc/index.ts +247 -3
  46. package/src/provider/index.test.ts +233 -0
  47. package/src/provider/index.ts +64 -1
  48. package/src/rpc.test.ts +190 -0
  49. package/src/shared/rpc/auth.ts +27 -0
  50. package/src/shared/rpc/defaults.ts +41 -0
  51. package/src/shared/types/common.ts +24 -0
  52. package/src/shared/types/index.ts +1 -0
  53. package/src/shared/types/meld.ts +302 -0
  54. package/src/shared/types/noah.ts +191 -29
  55. package/types.d.ts +65 -3
@@ -11,7 +11,7 @@ import { PortalMpcError } from './errors';
11
11
  import { sdkLogger } from '../logger';
12
12
  import { BackupMethods, } from '../index';
13
13
  import { generateTraceId } from '../shared/trace';
14
- const WEB_SDK_VERSION = '3.17.0';
14
+ const WEB_SDK_VERSION = '3.18.0';
15
15
  class Mpc {
16
16
  get ready() {
17
17
  return this._ready;
@@ -217,7 +217,10 @@ class Mpc {
217
217
  });
218
218
  }
219
219
  rawSign(curve, param, options) {
220
+ var _a;
220
221
  return __awaiter(this, void 0, void 0, function* () {
222
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : generateTraceId();
223
+ sdkLogger.debug(`[Portal MPC] rawSign started | traceId=${traceId}`);
221
224
  return this.handleRequestToIframeAndPost({
222
225
  methodMessage: 'portal:mpc:rawSign',
223
226
  errorMessage: 'portal:mpc:rawSignError',
@@ -226,7 +229,7 @@ class Mpc {
226
229
  param }, ((options === null || options === void 0 ? void 0 : options.signatureApprovalMemo) !== undefined && {
227
230
  signatureApprovalMemo: options.signatureApprovalMemo,
228
231
  })),
229
- traceId: options === null || options === void 0 ? void 0 : options.traceId,
232
+ traceId,
230
233
  });
231
234
  });
232
235
  }
@@ -705,16 +708,176 @@ class Mpc {
705
708
  });
706
709
  });
707
710
  }
708
- getPaymentMethods() {
711
+ getPaymentMethods(data) {
709
712
  return __awaiter(this, void 0, void 0, function* () {
710
713
  return this.handleRequestToIframeAndPost({
711
714
  methodMessage: 'portal:noah:getPaymentMethods',
712
715
  errorMessage: 'portal:noah:getPaymentMethodsError',
713
716
  resultMessage: 'portal:noah:getPaymentMethodsResult',
717
+ data,
718
+ });
719
+ });
720
+ }
721
+ meldCreateCustomer(data) {
722
+ return __awaiter(this, void 0, void 0, function* () {
723
+ return this.handleRequestToIframeAndPost({
724
+ methodMessage: 'portal:meld:createCustomer',
725
+ errorMessage: 'portal:meld:createCustomerError',
726
+ resultMessage: 'portal:meld:createCustomerResult',
727
+ data,
728
+ });
729
+ });
730
+ }
731
+ meldSearchCustomer() {
732
+ return __awaiter(this, void 0, void 0, function* () {
733
+ return this.handleRequestToIframeAndPost({
734
+ methodMessage: 'portal:meld:searchCustomer',
735
+ errorMessage: 'portal:meld:searchCustomerError',
736
+ resultMessage: 'portal:meld:searchCustomerResult',
714
737
  data: {},
715
738
  });
716
739
  });
717
740
  }
741
+ meldGetRetailQuote(data) {
742
+ return __awaiter(this, void 0, void 0, function* () {
743
+ return this.handleRequestToIframeAndPost({
744
+ methodMessage: 'portal:meld:getRetailQuote',
745
+ errorMessage: 'portal:meld:getRetailQuoteError',
746
+ resultMessage: 'portal:meld:getRetailQuoteResult',
747
+ data,
748
+ });
749
+ });
750
+ }
751
+ meldCreateRetailWidget(data) {
752
+ return __awaiter(this, void 0, void 0, function* () {
753
+ return this.handleRequestToIframeAndPost({
754
+ methodMessage: 'portal:meld:createRetailWidget',
755
+ errorMessage: 'portal:meld:createRetailWidgetError',
756
+ resultMessage: 'portal:meld:createRetailWidgetResult',
757
+ data,
758
+ });
759
+ });
760
+ }
761
+ meldSearchRetailTransactions(data) {
762
+ return __awaiter(this, void 0, void 0, function* () {
763
+ return this.handleRequestToIframeAndPost({
764
+ methodMessage: 'portal:meld:searchRetailTransactions',
765
+ errorMessage: 'portal:meld:searchRetailTransactionsError',
766
+ resultMessage: 'portal:meld:searchRetailTransactionsResult',
767
+ data,
768
+ });
769
+ });
770
+ }
771
+ meldGetRetailTransactionBySession(sessionId) {
772
+ return __awaiter(this, void 0, void 0, function* () {
773
+ return this.handleRequestToIframeAndPost({
774
+ methodMessage: 'portal:meld:getRetailTransactionBySession',
775
+ errorMessage: 'portal:meld:getRetailTransactionBySessionError',
776
+ resultMessage: 'portal:meld:getRetailTransactionBySessionResult',
777
+ data: sessionId,
778
+ });
779
+ });
780
+ }
781
+ meldGetRetailTransaction(id) {
782
+ return __awaiter(this, void 0, void 0, function* () {
783
+ return this.handleRequestToIframeAndPost({
784
+ methodMessage: 'portal:meld:getRetailTransaction',
785
+ errorMessage: 'portal:meld:getRetailTransactionError',
786
+ resultMessage: 'portal:meld:getRetailTransactionResult',
787
+ data: id,
788
+ });
789
+ });
790
+ }
791
+ meldGetServiceProviders(data) {
792
+ return __awaiter(this, void 0, void 0, function* () {
793
+ return this.handleRequestToIframeAndPost({
794
+ methodMessage: 'portal:meld:getServiceProviders',
795
+ errorMessage: 'portal:meld:getServiceProvidersError',
796
+ resultMessage: 'portal:meld:getServiceProvidersResult',
797
+ data: data !== null && data !== void 0 ? data : {},
798
+ });
799
+ });
800
+ }
801
+ meldGetCountries(data) {
802
+ return __awaiter(this, void 0, void 0, function* () {
803
+ return this.handleRequestToIframeAndPost({
804
+ methodMessage: 'portal:meld:getCountries',
805
+ errorMessage: 'portal:meld:getCountriesError',
806
+ resultMessage: 'portal:meld:getCountriesResult',
807
+ data: data !== null && data !== void 0 ? data : {},
808
+ });
809
+ });
810
+ }
811
+ meldGetFiatCurrencies(data) {
812
+ return __awaiter(this, void 0, void 0, function* () {
813
+ return this.handleRequestToIframeAndPost({
814
+ methodMessage: 'portal:meld:getFiatCurrencies',
815
+ errorMessage: 'portal:meld:getFiatCurrenciesError',
816
+ resultMessage: 'portal:meld:getFiatCurrenciesResult',
817
+ data: data !== null && data !== void 0 ? data : {},
818
+ });
819
+ });
820
+ }
821
+ meldGetCryptoCurrencies(data) {
822
+ return __awaiter(this, void 0, void 0, function* () {
823
+ return this.handleRequestToIframeAndPost({
824
+ methodMessage: 'portal:meld:getCryptoCurrencies',
825
+ errorMessage: 'portal:meld:getCryptoCurrenciesError',
826
+ resultMessage: 'portal:meld:getCryptoCurrenciesResult',
827
+ data: data !== null && data !== void 0 ? data : {},
828
+ });
829
+ });
830
+ }
831
+ meldGetPaymentMethods(data) {
832
+ return __awaiter(this, void 0, void 0, function* () {
833
+ return this.handleRequestToIframeAndPost({
834
+ methodMessage: 'portal:meld:getPaymentMethods',
835
+ errorMessage: 'portal:meld:getPaymentMethodsError',
836
+ resultMessage: 'portal:meld:getPaymentMethodsResult',
837
+ data: data !== null && data !== void 0 ? data : {},
838
+ });
839
+ });
840
+ }
841
+ meldGetDefaults(data) {
842
+ return __awaiter(this, void 0, void 0, function* () {
843
+ return this.handleRequestToIframeAndPost({
844
+ methodMessage: 'portal:meld:getDefaults',
845
+ errorMessage: 'portal:meld:getDefaultsError',
846
+ resultMessage: 'portal:meld:getDefaultsResult',
847
+ data: data !== null && data !== void 0 ? data : {},
848
+ });
849
+ });
850
+ }
851
+ meldGetBuyLimits(data) {
852
+ return __awaiter(this, void 0, void 0, function* () {
853
+ return this.handleRequestToIframeAndPost({
854
+ methodMessage: 'portal:meld:getBuyLimits',
855
+ errorMessage: 'portal:meld:getBuyLimitsError',
856
+ resultMessage: 'portal:meld:getBuyLimitsResult',
857
+ data: data !== null && data !== void 0 ? data : {},
858
+ });
859
+ });
860
+ }
861
+ meldGetSellLimits(data) {
862
+ return __awaiter(this, void 0, void 0, function* () {
863
+ return this.handleRequestToIframeAndPost({
864
+ methodMessage: 'portal:meld:getSellLimits',
865
+ errorMessage: 'portal:meld:getSellLimitsError',
866
+ resultMessage: 'portal:meld:getSellLimitsResult',
867
+ data: data !== null && data !== void 0 ? data : {},
868
+ });
869
+ });
870
+ }
871
+ meldGetKycLimits(data) {
872
+ return __awaiter(this, void 0, void 0, function* () {
873
+ return this.handleRequestToIframeAndPost({
874
+ methodMessage: 'portal:meld:getKycLimits',
875
+ errorMessage: 'portal:meld:getKycLimitsError',
876
+ resultMessage: 'portal:meld:getKycLimitsResult',
877
+ data: data !== null && data !== void 0 ? data : {},
878
+ });
879
+ });
880
+ }
718
881
  getSwapsQuoteV2(data, options) {
719
882
  return __awaiter(this, void 0, void 0, function* () {
720
883
  return this.handleRequestToIframeAndPost({
@@ -959,6 +1122,12 @@ class Mpc {
959
1122
  handleRequestToIframeAndPost({ methodMessage, errorMessage, resultMessage, data, progressMessage, progressCallback, mapReturnValue, traceId: providedTraceId, }) {
960
1123
  return __awaiter(this, void 0, void 0, function* () {
961
1124
  // Single traceId per operation: use provided or generate. Propagates to iframe and all internal REST/MPC calls.
1125
+ if (!providedTraceId &&
1126
+ (methodMessage.startsWith('portal:wasm:') ||
1127
+ methodMessage.startsWith('portal:mpc:') ||
1128
+ methodMessage.startsWith('portal:accountAbstraction:'))) {
1129
+ sdkLogger.debug(`[Portal] No traceId propagated to handleRequestToIframeAndPost for method=${methodMessage}; generating a new one.`);
1130
+ }
962
1131
  const traceId = providedTraceId !== null && providedTraceId !== void 0 ? providedTraceId : generateTraceId();
963
1132
  sdkLogger.debug('[Portal] request traceId:', traceId, 'method:', methodMessage);
964
1133
  return new Promise((resolve, reject) => {
@@ -1175,6 +1344,33 @@ class Mpc {
1175
1344
  // Update the address
1176
1345
  const address = yield this.getAddress();
1177
1346
  this.portal.address = address;
1347
+ // Detect if wallet shares were cleared from storage (e.g., Safari ITP).
1348
+ // Must be awaited before triggerReady so the event fires before app callbacks run.
1349
+ try {
1350
+ const [client, shares] = yield Promise.all([
1351
+ this.getClient(),
1352
+ this.checkSharesOnDevice(),
1353
+ ]);
1354
+ const completedWallets = client.wallets.filter((w) => w.signingSharePairs.some((sp) => sp.status === 'completed'));
1355
+ const requiredCurves = completedWallets.map((w) => w.curve);
1356
+ const walletOnDevice = requiredCurves.length > 0 &&
1357
+ requiredCurves.every((curve) => !!shares[curve]);
1358
+ // No completed wallets means the user is in initial setup — no prior
1359
+ // device state to have been lost.
1360
+ const isInitialSetup = completedWallets.length === 0;
1361
+ const shouldEmitWalletNotOnDevice = !isInitialSetup && !walletOnDevice && !client.ejectedAt;
1362
+ if (shouldEmitWalletNotOnDevice) {
1363
+ const isBackedUp = client.wallets.some((w) => w.backupSharePairs.some((bp) => bp.status === 'completed'));
1364
+ this.portal.triggerWalletNotOnDevice({
1365
+ clientId: client.id,
1366
+ isBackedUp,
1367
+ reason: 'storage_cleared',
1368
+ });
1369
+ }
1370
+ }
1371
+ catch (detectionError) {
1372
+ sdkLogger.warn('[Portal] walletNotOnDevice detection failed (initialization continues):', detectionError);
1373
+ }
1178
1374
  // Trigger the ready callback
1179
1375
  this.portal.triggerReady();
1180
1376
  }