@portal-hq/web 3.17.0 → 3.18.0-alpha.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 +3 -2
  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
@@ -3764,6 +3764,513 @@ describe('Mpc', () => {
3764
3764
  });
3765
3765
  });
3766
3766
  });
3767
+ describe('meldCreateCustomer', () => {
3768
+ const args = constants_1.mockMeldCreateCustomerRequest;
3769
+ const res = constants_1.mockMeldCreateCustomerResponse;
3770
+ it('should successfully return the created customer', (done) => {
3771
+ var _a;
3772
+ jest
3773
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3774
+ .mockImplementation((message, origin) => {
3775
+ const { type, data } = message;
3776
+ expect(type).toEqual('portal:meld:createCustomer');
3777
+ expect(data).toMatchObject(args);
3778
+ expect(typeof message.traceId).toBe('string');
3779
+ expect(origin).toEqual(mockHostOrigin);
3780
+ window.dispatchEvent(new MessageEvent('message', {
3781
+ origin: mockHostOrigin,
3782
+ data: {
3783
+ type: 'portal:meld:createCustomerResult',
3784
+ data: res,
3785
+ },
3786
+ }));
3787
+ });
3788
+ mpc
3789
+ .meldCreateCustomer(args)
3790
+ .then((data) => {
3791
+ expect(data).toEqual(res);
3792
+ done();
3793
+ })
3794
+ .catch((_) => {
3795
+ expect(0).toEqual(1);
3796
+ done();
3797
+ });
3798
+ });
3799
+ it('should error out if the iframe sends an error message', (done) => {
3800
+ var _a;
3801
+ jest
3802
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3803
+ .mockImplementationOnce((message, origin) => {
3804
+ const { type } = message;
3805
+ expect(type).toEqual('portal:meld:createCustomer');
3806
+ expect(origin).toEqual(mockHostOrigin);
3807
+ window.dispatchEvent(new MessageEvent('message', {
3808
+ origin: mockHostOrigin,
3809
+ data: {
3810
+ type: 'portal:meld:createCustomerError',
3811
+ data: { code: 1, message: 'test' },
3812
+ },
3813
+ }));
3814
+ });
3815
+ mpc
3816
+ .meldCreateCustomer(args)
3817
+ .then(() => {
3818
+ expect(0).toEqual(1);
3819
+ done();
3820
+ })
3821
+ .catch((e) => {
3822
+ expect(e).toBeInstanceOf(errors_1.PortalMpcError);
3823
+ expect(e.message).toEqual('test');
3824
+ expect(e.code).toEqual(1);
3825
+ done();
3826
+ });
3827
+ });
3828
+ });
3829
+ describe('meldSearchCustomer', () => {
3830
+ const res = constants_1.mockMeldSearchCustomerResponse;
3831
+ it('should successfully return the customer data', (done) => {
3832
+ var _a;
3833
+ jest
3834
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3835
+ .mockImplementation((message, origin) => {
3836
+ const { type } = message;
3837
+ expect(type).toEqual('portal:meld:searchCustomer');
3838
+ expect(origin).toEqual(mockHostOrigin);
3839
+ window.dispatchEvent(new MessageEvent('message', {
3840
+ origin: mockHostOrigin,
3841
+ data: {
3842
+ type: 'portal:meld:searchCustomerResult',
3843
+ data: res,
3844
+ },
3845
+ }));
3846
+ });
3847
+ mpc
3848
+ .meldSearchCustomer()
3849
+ .then((data) => {
3850
+ expect(data).toEqual(res);
3851
+ done();
3852
+ })
3853
+ .catch((_) => {
3854
+ expect(0).toEqual(1);
3855
+ done();
3856
+ });
3857
+ });
3858
+ it('should error out if the iframe sends an error message', (done) => {
3859
+ var _a;
3860
+ jest
3861
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3862
+ .mockImplementationOnce((_message, _origin) => {
3863
+ window.dispatchEvent(new MessageEvent('message', {
3864
+ origin: mockHostOrigin,
3865
+ data: {
3866
+ type: 'portal:meld:searchCustomerError',
3867
+ data: { code: 2, message: 'not found' },
3868
+ },
3869
+ }));
3870
+ });
3871
+ mpc
3872
+ .meldSearchCustomer()
3873
+ .then(() => {
3874
+ expect(0).toEqual(1);
3875
+ done();
3876
+ })
3877
+ .catch((e) => {
3878
+ expect(e).toBeInstanceOf(errors_1.PortalMpcError);
3879
+ expect(e.code).toEqual(2);
3880
+ done();
3881
+ });
3882
+ });
3883
+ });
3884
+ describe('meldGetRetailQuote', () => {
3885
+ const args = constants_1.mockMeldGetRetailQuoteRequest;
3886
+ const res = constants_1.mockMeldGetRetailQuoteResponse;
3887
+ it('should successfully return the retail quote', (done) => {
3888
+ var _a;
3889
+ jest
3890
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3891
+ .mockImplementation((message, origin) => {
3892
+ const { type, data } = message;
3893
+ expect(type).toEqual('portal:meld:getRetailQuote');
3894
+ expect(data).toMatchObject(args);
3895
+ expect(typeof message.traceId).toBe('string');
3896
+ expect(origin).toEqual(mockHostOrigin);
3897
+ window.dispatchEvent(new MessageEvent('message', {
3898
+ origin: mockHostOrigin,
3899
+ data: {
3900
+ type: 'portal:meld:getRetailQuoteResult',
3901
+ data: res,
3902
+ },
3903
+ }));
3904
+ });
3905
+ mpc
3906
+ .meldGetRetailQuote(args)
3907
+ .then((data) => {
3908
+ expect(data).toEqual(res);
3909
+ done();
3910
+ })
3911
+ .catch((_) => {
3912
+ expect(0).toEqual(1);
3913
+ done();
3914
+ });
3915
+ });
3916
+ it('should error out if the iframe sends an error message', (done) => {
3917
+ var _a;
3918
+ jest
3919
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3920
+ .mockImplementationOnce((_message, _origin) => {
3921
+ window.dispatchEvent(new MessageEvent('message', {
3922
+ origin: mockHostOrigin,
3923
+ data: {
3924
+ type: 'portal:meld:getRetailQuoteError',
3925
+ data: { code: 1, message: 'test' },
3926
+ },
3927
+ }));
3928
+ });
3929
+ mpc
3930
+ .meldGetRetailQuote(args)
3931
+ .then(() => {
3932
+ expect(0).toEqual(1);
3933
+ done();
3934
+ })
3935
+ .catch((e) => {
3936
+ expect(e).toBeInstanceOf(errors_1.PortalMpcError);
3937
+ expect(e.message).toEqual('test');
3938
+ expect(e.code).toEqual(1);
3939
+ done();
3940
+ });
3941
+ });
3942
+ });
3943
+ describe('meldCreateRetailWidget', () => {
3944
+ const args = constants_1.mockMeldCreateRetailWidgetRequest;
3945
+ const res = constants_1.mockMeldCreateRetailWidgetResponse;
3946
+ it('should successfully return the retail widget', (done) => {
3947
+ var _a;
3948
+ jest
3949
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3950
+ .mockImplementation((message, origin) => {
3951
+ expect(message.type).toEqual('portal:meld:createRetailWidget');
3952
+ expect(message.data).toMatchObject(args);
3953
+ expect(origin).toEqual(mockHostOrigin);
3954
+ window.dispatchEvent(new MessageEvent('message', {
3955
+ origin: mockHostOrigin,
3956
+ data: { type: 'portal:meld:createRetailWidgetResult', data: res },
3957
+ }));
3958
+ });
3959
+ mpc
3960
+ .meldCreateRetailWidget(args)
3961
+ .then((data) => {
3962
+ expect(data).toEqual(res);
3963
+ done();
3964
+ })
3965
+ .catch((_) => {
3966
+ expect(0).toEqual(1);
3967
+ done();
3968
+ });
3969
+ });
3970
+ });
3971
+ describe('meldSearchRetailTransactions', () => {
3972
+ const res = constants_1.mockMeldSearchRetailTransactionsResponse;
3973
+ it('should successfully return transactions without params', (done) => {
3974
+ var _a;
3975
+ jest
3976
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
3977
+ .mockImplementation((message, origin) => {
3978
+ expect(message.type).toEqual('portal:meld:searchRetailTransactions');
3979
+ expect(origin).toEqual(mockHostOrigin);
3980
+ window.dispatchEvent(new MessageEvent('message', {
3981
+ origin: mockHostOrigin,
3982
+ data: { type: 'portal:meld:searchRetailTransactionsResult', data: res },
3983
+ }));
3984
+ });
3985
+ mpc
3986
+ .meldSearchRetailTransactions()
3987
+ .then((data) => {
3988
+ expect(data).toEqual(res);
3989
+ done();
3990
+ })
3991
+ .catch((_) => {
3992
+ expect(0).toEqual(1);
3993
+ done();
3994
+ });
3995
+ });
3996
+ });
3997
+ describe('meldGetRetailTransactionBySession', () => {
3998
+ const res = constants_1.mockMeldGetRetailTransactionResponse;
3999
+ it('should successfully return a transaction by session ID', (done) => {
4000
+ var _a;
4001
+ jest
4002
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4003
+ .mockImplementation((message, origin) => {
4004
+ expect(message.type).toEqual('portal:meld:getRetailTransactionBySession');
4005
+ expect(message.data).toEqual('ses-123');
4006
+ expect(origin).toEqual(mockHostOrigin);
4007
+ window.dispatchEvent(new MessageEvent('message', {
4008
+ origin: mockHostOrigin,
4009
+ data: { type: 'portal:meld:getRetailTransactionBySessionResult', data: res },
4010
+ }));
4011
+ });
4012
+ mpc
4013
+ .meldGetRetailTransactionBySession('ses-123')
4014
+ .then((data) => {
4015
+ expect(data).toEqual(res);
4016
+ done();
4017
+ })
4018
+ .catch((_) => {
4019
+ expect(0).toEqual(1);
4020
+ done();
4021
+ });
4022
+ });
4023
+ });
4024
+ describe('meldGetRetailTransaction', () => {
4025
+ const res = constants_1.mockMeldGetRetailTransactionResponse;
4026
+ it('should successfully return a transaction by ID', (done) => {
4027
+ var _a;
4028
+ jest
4029
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4030
+ .mockImplementation((message, origin) => {
4031
+ expect(message.type).toEqual('portal:meld:getRetailTransaction');
4032
+ expect(message.data).toEqual('tx-123');
4033
+ expect(origin).toEqual(mockHostOrigin);
4034
+ window.dispatchEvent(new MessageEvent('message', {
4035
+ origin: mockHostOrigin,
4036
+ data: { type: 'portal:meld:getRetailTransactionResult', data: res },
4037
+ }));
4038
+ });
4039
+ mpc
4040
+ .meldGetRetailTransaction('tx-123')
4041
+ .then((data) => {
4042
+ expect(data).toEqual(res);
4043
+ done();
4044
+ })
4045
+ .catch((_) => {
4046
+ expect(0).toEqual(1);
4047
+ done();
4048
+ });
4049
+ });
4050
+ });
4051
+ describe('meldGetServiceProviders', () => {
4052
+ const res = constants_1.mockMeldDiscoveryResponse;
4053
+ it('should successfully return service providers without params', (done) => {
4054
+ var _a;
4055
+ jest
4056
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4057
+ .mockImplementation((message, origin) => {
4058
+ expect(message.type).toEqual('portal:meld:getServiceProviders');
4059
+ expect(origin).toEqual(mockHostOrigin);
4060
+ window.dispatchEvent(new MessageEvent('message', {
4061
+ origin: mockHostOrigin,
4062
+ data: { type: 'portal:meld:getServiceProvidersResult', data: res },
4063
+ }));
4064
+ });
4065
+ mpc
4066
+ .meldGetServiceProviders()
4067
+ .then((data) => {
4068
+ expect(data).toEqual(res);
4069
+ done();
4070
+ })
4071
+ .catch((_) => {
4072
+ expect(0).toEqual(1);
4073
+ done();
4074
+ });
4075
+ });
4076
+ it('should pass params to the iframe when provided', (done) => {
4077
+ var _a;
4078
+ const params = constants_1.mockMeldDiscoveryParams;
4079
+ jest
4080
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4081
+ .mockImplementation((message, origin) => {
4082
+ expect(message.type).toEqual('portal:meld:getServiceProviders');
4083
+ expect(message.data).toMatchObject(params);
4084
+ expect(origin).toEqual(mockHostOrigin);
4085
+ window.dispatchEvent(new MessageEvent('message', {
4086
+ origin: mockHostOrigin,
4087
+ data: { type: 'portal:meld:getServiceProvidersResult', data: res },
4088
+ }));
4089
+ });
4090
+ mpc
4091
+ .meldGetServiceProviders(params)
4092
+ .then(() => done())
4093
+ .catch((_) => {
4094
+ expect(0).toEqual(1);
4095
+ done();
4096
+ });
4097
+ });
4098
+ });
4099
+ describe('meldGetCountries', () => {
4100
+ it('should successfully return countries', (done) => {
4101
+ var _a;
4102
+ const res = constants_1.mockMeldDiscoveryResponse;
4103
+ jest
4104
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4105
+ .mockImplementation((message, origin) => {
4106
+ expect(message.type).toEqual('portal:meld:getCountries');
4107
+ expect(origin).toEqual(mockHostOrigin);
4108
+ window.dispatchEvent(new MessageEvent('message', {
4109
+ origin: mockHostOrigin,
4110
+ data: { type: 'portal:meld:getCountriesResult', data: res },
4111
+ }));
4112
+ });
4113
+ mpc
4114
+ .meldGetCountries()
4115
+ .then((data) => {
4116
+ expect(data).toEqual(res);
4117
+ done();
4118
+ })
4119
+ .catch((_) => {
4120
+ expect(0).toEqual(1);
4121
+ done();
4122
+ });
4123
+ });
4124
+ it('should error out if the iframe sends an error message', (done) => {
4125
+ var _a;
4126
+ jest
4127
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4128
+ .mockImplementationOnce((_message, _origin) => {
4129
+ window.dispatchEvent(new MessageEvent('message', {
4130
+ origin: mockHostOrigin,
4131
+ data: { type: 'portal:meld:getCountriesError', data: { code: 1, message: 'test' } },
4132
+ }));
4133
+ });
4134
+ mpc
4135
+ .meldGetCountries()
4136
+ .then(() => {
4137
+ expect(0).toEqual(1);
4138
+ done();
4139
+ })
4140
+ .catch((e) => {
4141
+ expect(e).toBeInstanceOf(errors_1.PortalMpcError);
4142
+ done();
4143
+ });
4144
+ });
4145
+ });
4146
+ describe('meldGetFiatCurrencies', () => {
4147
+ it('should successfully return fiat currencies', (done) => {
4148
+ var _a;
4149
+ const res = constants_1.mockMeldDiscoveryResponse;
4150
+ jest
4151
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4152
+ .mockImplementation((message, origin) => {
4153
+ expect(message.type).toEqual('portal:meld:getFiatCurrencies');
4154
+ expect(origin).toEqual(mockHostOrigin);
4155
+ window.dispatchEvent(new MessageEvent('message', {
4156
+ origin: mockHostOrigin,
4157
+ data: { type: 'portal:meld:getFiatCurrenciesResult', data: res },
4158
+ }));
4159
+ });
4160
+ mpc
4161
+ .meldGetFiatCurrencies()
4162
+ .then((data) => {
4163
+ expect(data).toEqual(res);
4164
+ done();
4165
+ })
4166
+ .catch((_) => {
4167
+ expect(0).toEqual(1);
4168
+ done();
4169
+ });
4170
+ });
4171
+ });
4172
+ describe('meldGetCryptoCurrencies', () => {
4173
+ it('should successfully return crypto currencies', (done) => {
4174
+ var _a;
4175
+ const res = constants_1.mockMeldDiscoveryResponse;
4176
+ jest
4177
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4178
+ .mockImplementation((message, origin) => {
4179
+ expect(message.type).toEqual('portal:meld:getCryptoCurrencies');
4180
+ expect(origin).toEqual(mockHostOrigin);
4181
+ window.dispatchEvent(new MessageEvent('message', {
4182
+ origin: mockHostOrigin,
4183
+ data: { type: 'portal:meld:getCryptoCurrenciesResult', data: res },
4184
+ }));
4185
+ });
4186
+ mpc.meldGetCryptoCurrencies().then((data) => { expect(data).toEqual(res); done(); }).catch((_) => { expect(0).toEqual(1); done(); });
4187
+ });
4188
+ });
4189
+ describe('meldGetPaymentMethods', () => {
4190
+ it('should successfully return payment methods', (done) => {
4191
+ var _a;
4192
+ const res = constants_1.mockMeldDiscoveryResponse;
4193
+ jest
4194
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4195
+ .mockImplementation((message, origin) => {
4196
+ expect(message.type).toEqual('portal:meld:getPaymentMethods');
4197
+ expect(origin).toEqual(mockHostOrigin);
4198
+ window.dispatchEvent(new MessageEvent('message', {
4199
+ origin: mockHostOrigin,
4200
+ data: { type: 'portal:meld:getPaymentMethodsResult', data: res },
4201
+ }));
4202
+ });
4203
+ mpc.meldGetPaymentMethods().then((data) => { expect(data).toEqual(res); done(); }).catch((_) => { expect(0).toEqual(1); done(); });
4204
+ });
4205
+ });
4206
+ describe('meldGetDefaults', () => {
4207
+ it('should successfully return defaults', (done) => {
4208
+ var _a;
4209
+ const res = constants_1.mockMeldDiscoveryResponse;
4210
+ jest
4211
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4212
+ .mockImplementation((message, origin) => {
4213
+ expect(message.type).toEqual('portal:meld:getDefaults');
4214
+ expect(origin).toEqual(mockHostOrigin);
4215
+ window.dispatchEvent(new MessageEvent('message', {
4216
+ origin: mockHostOrigin,
4217
+ data: { type: 'portal:meld:getDefaultsResult', data: res },
4218
+ }));
4219
+ });
4220
+ mpc.meldGetDefaults().then((data) => { expect(data).toEqual(res); done(); }).catch((_) => { expect(0).toEqual(1); done(); });
4221
+ });
4222
+ });
4223
+ describe('meldGetBuyLimits', () => {
4224
+ it('should successfully return buy limits', (done) => {
4225
+ var _a;
4226
+ const res = constants_1.mockMeldDiscoveryResponse;
4227
+ jest
4228
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4229
+ .mockImplementation((message, origin) => {
4230
+ expect(message.type).toEqual('portal:meld:getBuyLimits');
4231
+ expect(origin).toEqual(mockHostOrigin);
4232
+ window.dispatchEvent(new MessageEvent('message', {
4233
+ origin: mockHostOrigin,
4234
+ data: { type: 'portal:meld:getBuyLimitsResult', data: res },
4235
+ }));
4236
+ });
4237
+ mpc.meldGetBuyLimits().then((data) => { expect(data).toEqual(res); done(); }).catch((_) => { expect(0).toEqual(1); done(); });
4238
+ });
4239
+ });
4240
+ describe('meldGetSellLimits', () => {
4241
+ it('should successfully return sell limits', (done) => {
4242
+ var _a;
4243
+ const res = constants_1.mockMeldDiscoveryResponse;
4244
+ jest
4245
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4246
+ .mockImplementation((message, origin) => {
4247
+ expect(message.type).toEqual('portal:meld:getSellLimits');
4248
+ expect(origin).toEqual(mockHostOrigin);
4249
+ window.dispatchEvent(new MessageEvent('message', {
4250
+ origin: mockHostOrigin,
4251
+ data: { type: 'portal:meld:getSellLimitsResult', data: res },
4252
+ }));
4253
+ });
4254
+ mpc.meldGetSellLimits().then((data) => { expect(data).toEqual(res); done(); }).catch((_) => { expect(0).toEqual(1); done(); });
4255
+ });
4256
+ });
4257
+ describe('meldGetKycLimits', () => {
4258
+ it('should successfully return KYC limits', (done) => {
4259
+ var _a;
4260
+ const res = constants_1.mockMeldDiscoveryResponse;
4261
+ jest
4262
+ .spyOn((_a = mpc.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow, 'postMessage')
4263
+ .mockImplementation((message, origin) => {
4264
+ expect(message.type).toEqual('portal:meld:getKycLimits');
4265
+ expect(origin).toEqual(mockHostOrigin);
4266
+ window.dispatchEvent(new MessageEvent('message', {
4267
+ origin: mockHostOrigin,
4268
+ data: { type: 'portal:meld:getKycLimitsResult', data: res },
4269
+ }));
4270
+ });
4271
+ mpc.meldGetKycLimits().then((data) => { expect(data).toEqual(res); done(); }).catch((_) => { expect(0).toEqual(1); done(); });
4272
+ });
4273
+ });
3767
4274
  describe('accountAbstractionBuildBatchedUserOp', () => {
3768
4275
  const args = constants_1.mockBuildBatchedUserOpRequest;
3769
4276
  const res = constants_1.mockBuildBatchedUserOpResponse;
@@ -3898,4 +4405,131 @@ describe('Mpc', () => {
3898
4405
  });
3899
4406
  });
3900
4407
  });
4408
+ describe('walletNotOnDevice detection', () => {
4409
+ const makeClient = (overrides = {}) => (Object.assign({ id: 'client-test', address: constants_1.mockAddress, ejectedAt: null, custodian: { id: 'c', name: 'c' }, environment: { id: 'e', name: 'e', backupWithPortalEnabled: false, isMultiBackupEnabled: false }, isAccountAbstracted: false, metadata: { namespaces: {} }, wallets: [] }, overrides));
4410
+ const makeWallet = (curve, signingStatus, backupStatus) => ({
4411
+ id: `wallet-${curve}`,
4412
+ createdAt: '2024-01-01T00:00:00.000Z',
4413
+ curve,
4414
+ publicKey: 'pk',
4415
+ signingSharePairs: [{ id: 'sp1', createdAt: '2024-01-01T00:00:00.000Z', status: signingStatus }],
4416
+ backupSharePairs: [
4417
+ {
4418
+ id: 'bp1',
4419
+ createdAt: '2024-01-01T00:00:00.000Z',
4420
+ backupMethod: index_1.BackupMethods.password,
4421
+ status: backupStatus,
4422
+ },
4423
+ ],
4424
+ });
4425
+ const dispatchReady = () => {
4426
+ window.dispatchEvent(new MessageEvent('message', {
4427
+ origin: `https://${constants_1.mockHost}`,
4428
+ data: { type: 'portal:ready', data: true },
4429
+ }));
4430
+ };
4431
+ const flushPromises = () => new Promise((resolve) => setTimeout(resolve, 0));
4432
+ beforeEach(() => {
4433
+ jest.spyOn(mpc, 'getAddress').mockResolvedValue(constants_1.mockAddress);
4434
+ mpc.waitForReadyMessage();
4435
+ });
4436
+ it('does not emit when client has no wallets (new user / initial setup)', () => __awaiter(void 0, void 0, void 0, function* () {
4437
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({ wallets: [] }));
4438
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false });
4439
+ dispatchReady();
4440
+ yield flushPromises();
4441
+ expect(portal_1.default.triggerWalletNotOnDevice).not.toHaveBeenCalled();
4442
+ expect(portal_1.default.triggerReady).toHaveBeenCalled();
4443
+ }));
4444
+ it('does not emit when wallets exist but all signing share pairs are incomplete (setup in progress)', () => __awaiter(void 0, void 0, void 0, function* () {
4445
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4446
+ wallets: [
4447
+ makeWallet(index_1.PortalCurve.SECP256K1, 'incomplete', 'incomplete'),
4448
+ makeWallet(index_1.PortalCurve.ED25519, 'incomplete', 'incomplete'),
4449
+ ],
4450
+ }));
4451
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false });
4452
+ dispatchReady();
4453
+ yield flushPromises();
4454
+ expect(portal_1.default.triggerWalletNotOnDevice).not.toHaveBeenCalled();
4455
+ expect(portal_1.default.triggerReady).toHaveBeenCalled();
4456
+ }));
4457
+ it('does not emit when wallet is present on device', () => __awaiter(void 0, void 0, void 0, function* () {
4458
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4459
+ wallets: [
4460
+ makeWallet(index_1.PortalCurve.SECP256K1, 'completed', 'completed'),
4461
+ makeWallet(index_1.PortalCurve.ED25519, 'completed', 'completed'),
4462
+ ],
4463
+ }));
4464
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: true, ED25519: true });
4465
+ dispatchReady();
4466
+ yield flushPromises();
4467
+ expect(portal_1.default.triggerWalletNotOnDevice).not.toHaveBeenCalled();
4468
+ }));
4469
+ it('emits walletNotOnDevice with isBackedUp=false when wallet is not on device and not backed up', () => __awaiter(void 0, void 0, void 0, function* () {
4470
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4471
+ wallets: [
4472
+ makeWallet(index_1.PortalCurve.SECP256K1, 'completed', 'incomplete'),
4473
+ makeWallet(index_1.PortalCurve.ED25519, 'completed', 'incomplete'),
4474
+ ],
4475
+ }));
4476
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false });
4477
+ dispatchReady();
4478
+ yield flushPromises();
4479
+ expect(portal_1.default.triggerWalletNotOnDevice).toHaveBeenCalledWith({
4480
+ clientId: 'client-test',
4481
+ isBackedUp: false,
4482
+ reason: 'storage_cleared',
4483
+ });
4484
+ }));
4485
+ it('emits walletNotOnDevice with isBackedUp=true when at least one backup is complete', () => __awaiter(void 0, void 0, void 0, function* () {
4486
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4487
+ wallets: [makeWallet(index_1.PortalCurve.SECP256K1, 'completed', 'completed')],
4488
+ }));
4489
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false });
4490
+ dispatchReady();
4491
+ yield flushPromises();
4492
+ expect(portal_1.default.triggerWalletNotOnDevice).toHaveBeenCalledWith({
4493
+ clientId: 'client-test',
4494
+ isBackedUp: true,
4495
+ reason: 'storage_cleared',
4496
+ });
4497
+ }));
4498
+ it('does not emit for EVM-only client when SECP256K1 share is present (ED25519 absence is irrelevant)', () => __awaiter(void 0, void 0, void 0, function* () {
4499
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4500
+ wallets: [makeWallet(index_1.PortalCurve.SECP256K1, 'completed', 'incomplete')],
4501
+ }));
4502
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: true, ED25519: false });
4503
+ dispatchReady();
4504
+ yield flushPromises();
4505
+ expect(portal_1.default.triggerWalletNotOnDevice).not.toHaveBeenCalled();
4506
+ }));
4507
+ it('emits for EVM-only client when SECP256K1 share is missing', () => __awaiter(void 0, void 0, void 0, function* () {
4508
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4509
+ wallets: [makeWallet(index_1.PortalCurve.SECP256K1, 'completed', 'incomplete')],
4510
+ }));
4511
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false });
4512
+ dispatchReady();
4513
+ yield flushPromises();
4514
+ expect(portal_1.default.triggerWalletNotOnDevice).toHaveBeenCalled();
4515
+ }));
4516
+ it('does not emit when wallet is ejected (recovery is impossible)', () => __awaiter(void 0, void 0, void 0, function* () {
4517
+ jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({
4518
+ ejectedAt: '2024-06-01T00:00:00.000Z',
4519
+ wallets: [makeWallet(index_1.PortalCurve.SECP256K1, 'completed', 'incomplete')],
4520
+ }));
4521
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false });
4522
+ dispatchReady();
4523
+ yield flushPromises();
4524
+ expect(portal_1.default.triggerWalletNotOnDevice).not.toHaveBeenCalled();
4525
+ }));
4526
+ it('still calls triggerReady when detection throws (detection must not block initialization)', () => __awaiter(void 0, void 0, void 0, function* () {
4527
+ jest.spyOn(mpc, 'getClient').mockRejectedValue(new Error('network error'));
4528
+ jest.spyOn(mpc, 'checkSharesOnDevice').mockRejectedValue(new Error('network error'));
4529
+ dispatchReady();
4530
+ yield flushPromises();
4531
+ expect(portal_1.default.triggerWalletNotOnDevice).not.toHaveBeenCalled();
4532
+ expect(portal_1.default.triggerReady).toHaveBeenCalled();
4533
+ }));
4534
+ });
3901
4535
  });