@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.
- package/lib/commonjs/index.js +62 -20
- package/lib/commonjs/index.test.js +51 -10
- package/lib/commonjs/integrations/ramps/index.js +2 -0
- package/lib/commonjs/integrations/ramps/meld/index.js +121 -0
- package/lib/commonjs/integrations/ramps/meld/index.test.js +162 -0
- package/lib/commonjs/integrations/ramps/noah/index.js +2 -2
- package/lib/commonjs/integrations/ramps/noah/index.test.js +11 -2
- package/lib/commonjs/mpc/index.js +199 -3
- package/lib/commonjs/mpc/index.test.js +634 -0
- package/lib/commonjs/provider/index.js +44 -2
- package/lib/commonjs/provider/index.test.js +186 -0
- package/lib/commonjs/rpc.test.js +162 -0
- package/lib/commonjs/shared/rpc/auth.js +29 -0
- package/lib/commonjs/shared/rpc/defaults.js +40 -0
- package/lib/commonjs/shared/types/index.js +1 -0
- package/lib/commonjs/shared/types/meld.js +2 -0
- package/lib/esm/index.js +59 -19
- package/lib/esm/index.test.js +51 -10
- package/lib/esm/integrations/ramps/index.js +2 -0
- package/lib/esm/integrations/ramps/meld/index.js +118 -0
- package/lib/esm/integrations/ramps/meld/index.test.js +157 -0
- package/lib/esm/integrations/ramps/noah/index.js +2 -2
- package/lib/esm/integrations/ramps/noah/index.test.js +11 -2
- package/lib/esm/mpc/index.js +199 -3
- package/lib/esm/mpc/index.test.js +635 -1
- package/lib/esm/provider/index.js +44 -2
- package/lib/esm/provider/index.test.js +186 -0
- package/lib/esm/rpc.test.js +157 -0
- package/lib/esm/shared/rpc/auth.js +25 -0
- package/lib/esm/shared/rpc/defaults.js +36 -0
- package/lib/esm/shared/types/index.js +1 -0
- package/lib/esm/shared/types/meld.js +1 -0
- package/noah-types.d.ts +17 -1
- package/package.json +1 -1
- package/src/__mocks/constants.ts +68 -0
- package/src/__mocks/portal/portal.ts +0 -1
- package/src/index.test.ts +90 -0
- package/src/index.ts +159 -7
- package/src/integrations/ramps/index.ts +3 -0
- package/src/integrations/ramps/meld/index.test.ts +189 -0
- package/src/integrations/ramps/meld/index.ts +149 -0
- package/src/integrations/ramps/noah/index.test.ts +11 -2
- package/src/integrations/ramps/noah/index.ts +5 -2
- package/src/mpc/index.test.ts +804 -7
- package/src/mpc/index.ts +247 -3
- package/src/provider/index.test.ts +233 -0
- package/src/provider/index.ts +64 -1
- package/src/rpc.test.ts +190 -0
- package/src/shared/rpc/auth.ts +27 -0
- package/src/shared/rpc/defaults.ts +41 -0
- package/src/shared/types/common.ts +24 -0
- package/src/shared/types/index.ts +1 -0
- package/src/shared/types/meld.ts +302 -0
- package/src/shared/types/noah.ts +191 -29
- package/types.d.ts +65 -3
package/src/mpc/index.test.ts
CHANGED
|
@@ -80,6 +80,17 @@ import {
|
|
|
80
80
|
mockBlockaidScanTokensResponse,
|
|
81
81
|
mockBlockaidScanUrlRequest,
|
|
82
82
|
mockBlockaidScanUrlResponse,
|
|
83
|
+
mockMeldCreateCustomerRequest,
|
|
84
|
+
mockMeldCreateCustomerResponse,
|
|
85
|
+
mockMeldSearchCustomerResponse,
|
|
86
|
+
mockMeldGetRetailQuoteRequest,
|
|
87
|
+
mockMeldGetRetailQuoteResponse,
|
|
88
|
+
mockMeldCreateRetailWidgetRequest,
|
|
89
|
+
mockMeldCreateRetailWidgetResponse,
|
|
90
|
+
mockMeldSearchRetailTransactionsResponse,
|
|
91
|
+
mockMeldGetRetailTransactionResponse,
|
|
92
|
+
mockMeldDiscoveryResponse,
|
|
93
|
+
mockMeldDiscoveryParams,
|
|
83
94
|
mockBuildBatchedUserOpRequest,
|
|
84
95
|
mockBuildBatchedUserOpResponse,
|
|
85
96
|
mockBroadcastBatchedUserOpRequest,
|
|
@@ -4452,6 +4463,606 @@ describe('Mpc', () => {
|
|
|
4452
4463
|
})
|
|
4453
4464
|
})
|
|
4454
4465
|
|
|
4466
|
+
describe('meldCreateCustomer', () => {
|
|
4467
|
+
const args = mockMeldCreateCustomerRequest
|
|
4468
|
+
const res = mockMeldCreateCustomerResponse
|
|
4469
|
+
|
|
4470
|
+
it('should successfully return the created customer', (done) => {
|
|
4471
|
+
jest
|
|
4472
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4473
|
+
.mockImplementation((message: any, origin?) => {
|
|
4474
|
+
const { type, data } = message
|
|
4475
|
+
|
|
4476
|
+
expect(type).toEqual('portal:meld:createCustomer')
|
|
4477
|
+
expect(data).toMatchObject(args)
|
|
4478
|
+
expect(typeof message.traceId).toBe('string')
|
|
4479
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4480
|
+
|
|
4481
|
+
window.dispatchEvent(
|
|
4482
|
+
new MessageEvent('message', {
|
|
4483
|
+
origin: mockHostOrigin,
|
|
4484
|
+
data: {
|
|
4485
|
+
type: 'portal:meld:createCustomerResult',
|
|
4486
|
+
data: res,
|
|
4487
|
+
},
|
|
4488
|
+
}),
|
|
4489
|
+
)
|
|
4490
|
+
})
|
|
4491
|
+
|
|
4492
|
+
mpc
|
|
4493
|
+
.meldCreateCustomer(args)
|
|
4494
|
+
.then((data) => {
|
|
4495
|
+
expect(data).toEqual(res)
|
|
4496
|
+
done()
|
|
4497
|
+
})
|
|
4498
|
+
.catch((_) => {
|
|
4499
|
+
expect(0).toEqual(1)
|
|
4500
|
+
done()
|
|
4501
|
+
})
|
|
4502
|
+
})
|
|
4503
|
+
|
|
4504
|
+
it('should error out if the iframe sends an error message', (done) => {
|
|
4505
|
+
jest
|
|
4506
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4507
|
+
.mockImplementationOnce((message: any, origin?) => {
|
|
4508
|
+
const { type } = message
|
|
4509
|
+
|
|
4510
|
+
expect(type).toEqual('portal:meld:createCustomer')
|
|
4511
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4512
|
+
|
|
4513
|
+
window.dispatchEvent(
|
|
4514
|
+
new MessageEvent('message', {
|
|
4515
|
+
origin: mockHostOrigin,
|
|
4516
|
+
data: {
|
|
4517
|
+
type: 'portal:meld:createCustomerError',
|
|
4518
|
+
data: { code: 1, message: 'test' },
|
|
4519
|
+
},
|
|
4520
|
+
}),
|
|
4521
|
+
)
|
|
4522
|
+
})
|
|
4523
|
+
|
|
4524
|
+
mpc
|
|
4525
|
+
.meldCreateCustomer(args)
|
|
4526
|
+
.then(() => {
|
|
4527
|
+
expect(0).toEqual(1)
|
|
4528
|
+
done()
|
|
4529
|
+
})
|
|
4530
|
+
.catch((e) => {
|
|
4531
|
+
expect(e).toBeInstanceOf(PortalMpcError)
|
|
4532
|
+
expect(e.message).toEqual('test')
|
|
4533
|
+
expect(e.code).toEqual(1)
|
|
4534
|
+
done()
|
|
4535
|
+
})
|
|
4536
|
+
})
|
|
4537
|
+
})
|
|
4538
|
+
|
|
4539
|
+
describe('meldSearchCustomer', () => {
|
|
4540
|
+
const res = mockMeldSearchCustomerResponse
|
|
4541
|
+
|
|
4542
|
+
it('should successfully return the customer data', (done) => {
|
|
4543
|
+
jest
|
|
4544
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4545
|
+
.mockImplementation((message: any, origin?) => {
|
|
4546
|
+
const { type } = message
|
|
4547
|
+
|
|
4548
|
+
expect(type).toEqual('portal:meld:searchCustomer')
|
|
4549
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4550
|
+
|
|
4551
|
+
window.dispatchEvent(
|
|
4552
|
+
new MessageEvent('message', {
|
|
4553
|
+
origin: mockHostOrigin,
|
|
4554
|
+
data: {
|
|
4555
|
+
type: 'portal:meld:searchCustomerResult',
|
|
4556
|
+
data: res,
|
|
4557
|
+
},
|
|
4558
|
+
}),
|
|
4559
|
+
)
|
|
4560
|
+
})
|
|
4561
|
+
|
|
4562
|
+
mpc
|
|
4563
|
+
.meldSearchCustomer()
|
|
4564
|
+
.then((data) => {
|
|
4565
|
+
expect(data).toEqual(res)
|
|
4566
|
+
done()
|
|
4567
|
+
})
|
|
4568
|
+
.catch((_) => {
|
|
4569
|
+
expect(0).toEqual(1)
|
|
4570
|
+
done()
|
|
4571
|
+
})
|
|
4572
|
+
})
|
|
4573
|
+
|
|
4574
|
+
it('should error out if the iframe sends an error message', (done) => {
|
|
4575
|
+
jest
|
|
4576
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4577
|
+
.mockImplementationOnce((_message: any, _origin?) => {
|
|
4578
|
+
window.dispatchEvent(
|
|
4579
|
+
new MessageEvent('message', {
|
|
4580
|
+
origin: mockHostOrigin,
|
|
4581
|
+
data: {
|
|
4582
|
+
type: 'portal:meld:searchCustomerError',
|
|
4583
|
+
data: { code: 2, message: 'not found' },
|
|
4584
|
+
},
|
|
4585
|
+
}),
|
|
4586
|
+
)
|
|
4587
|
+
})
|
|
4588
|
+
|
|
4589
|
+
mpc
|
|
4590
|
+
.meldSearchCustomer()
|
|
4591
|
+
.then(() => {
|
|
4592
|
+
expect(0).toEqual(1)
|
|
4593
|
+
done()
|
|
4594
|
+
})
|
|
4595
|
+
.catch((e) => {
|
|
4596
|
+
expect(e).toBeInstanceOf(PortalMpcError)
|
|
4597
|
+
expect(e.code).toEqual(2)
|
|
4598
|
+
done()
|
|
4599
|
+
})
|
|
4600
|
+
})
|
|
4601
|
+
})
|
|
4602
|
+
|
|
4603
|
+
describe('meldGetRetailQuote', () => {
|
|
4604
|
+
const args = mockMeldGetRetailQuoteRequest
|
|
4605
|
+
const res = mockMeldGetRetailQuoteResponse
|
|
4606
|
+
|
|
4607
|
+
it('should successfully return the retail quote', (done) => {
|
|
4608
|
+
jest
|
|
4609
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4610
|
+
.mockImplementation((message: any, origin?) => {
|
|
4611
|
+
const { type, data } = message
|
|
4612
|
+
|
|
4613
|
+
expect(type).toEqual('portal:meld:getRetailQuote')
|
|
4614
|
+
expect(data).toMatchObject(args)
|
|
4615
|
+
expect(typeof message.traceId).toBe('string')
|
|
4616
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4617
|
+
|
|
4618
|
+
window.dispatchEvent(
|
|
4619
|
+
new MessageEvent('message', {
|
|
4620
|
+
origin: mockHostOrigin,
|
|
4621
|
+
data: {
|
|
4622
|
+
type: 'portal:meld:getRetailQuoteResult',
|
|
4623
|
+
data: res,
|
|
4624
|
+
},
|
|
4625
|
+
}),
|
|
4626
|
+
)
|
|
4627
|
+
})
|
|
4628
|
+
|
|
4629
|
+
mpc
|
|
4630
|
+
.meldGetRetailQuote(args)
|
|
4631
|
+
.then((data) => {
|
|
4632
|
+
expect(data).toEqual(res)
|
|
4633
|
+
done()
|
|
4634
|
+
})
|
|
4635
|
+
.catch((_) => {
|
|
4636
|
+
expect(0).toEqual(1)
|
|
4637
|
+
done()
|
|
4638
|
+
})
|
|
4639
|
+
})
|
|
4640
|
+
|
|
4641
|
+
it('should error out if the iframe sends an error message', (done) => {
|
|
4642
|
+
jest
|
|
4643
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4644
|
+
.mockImplementationOnce((_message: any, _origin?) => {
|
|
4645
|
+
window.dispatchEvent(
|
|
4646
|
+
new MessageEvent('message', {
|
|
4647
|
+
origin: mockHostOrigin,
|
|
4648
|
+
data: {
|
|
4649
|
+
type: 'portal:meld:getRetailQuoteError',
|
|
4650
|
+
data: { code: 1, message: 'test' },
|
|
4651
|
+
},
|
|
4652
|
+
}),
|
|
4653
|
+
)
|
|
4654
|
+
})
|
|
4655
|
+
|
|
4656
|
+
mpc
|
|
4657
|
+
.meldGetRetailQuote(args)
|
|
4658
|
+
.then(() => {
|
|
4659
|
+
expect(0).toEqual(1)
|
|
4660
|
+
done()
|
|
4661
|
+
})
|
|
4662
|
+
.catch((e) => {
|
|
4663
|
+
expect(e).toBeInstanceOf(PortalMpcError)
|
|
4664
|
+
expect(e.message).toEqual('test')
|
|
4665
|
+
expect(e.code).toEqual(1)
|
|
4666
|
+
done()
|
|
4667
|
+
})
|
|
4668
|
+
})
|
|
4669
|
+
})
|
|
4670
|
+
|
|
4671
|
+
describe('meldCreateRetailWidget', () => {
|
|
4672
|
+
const args = mockMeldCreateRetailWidgetRequest
|
|
4673
|
+
const res = mockMeldCreateRetailWidgetResponse
|
|
4674
|
+
|
|
4675
|
+
it('should successfully return the retail widget', (done) => {
|
|
4676
|
+
jest
|
|
4677
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4678
|
+
.mockImplementation((message: any, origin?) => {
|
|
4679
|
+
expect(message.type).toEqual('portal:meld:createRetailWidget')
|
|
4680
|
+
expect(message.data).toMatchObject(args)
|
|
4681
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4682
|
+
|
|
4683
|
+
window.dispatchEvent(
|
|
4684
|
+
new MessageEvent('message', {
|
|
4685
|
+
origin: mockHostOrigin,
|
|
4686
|
+
data: { type: 'portal:meld:createRetailWidgetResult', data: res },
|
|
4687
|
+
}),
|
|
4688
|
+
)
|
|
4689
|
+
})
|
|
4690
|
+
|
|
4691
|
+
mpc
|
|
4692
|
+
.meldCreateRetailWidget(args)
|
|
4693
|
+
.then((data) => {
|
|
4694
|
+
expect(data).toEqual(res)
|
|
4695
|
+
done()
|
|
4696
|
+
})
|
|
4697
|
+
.catch((_) => {
|
|
4698
|
+
expect(0).toEqual(1)
|
|
4699
|
+
done()
|
|
4700
|
+
})
|
|
4701
|
+
})
|
|
4702
|
+
})
|
|
4703
|
+
|
|
4704
|
+
describe('meldSearchRetailTransactions', () => {
|
|
4705
|
+
const res = mockMeldSearchRetailTransactionsResponse
|
|
4706
|
+
|
|
4707
|
+
it('should successfully return transactions without params', (done) => {
|
|
4708
|
+
jest
|
|
4709
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4710
|
+
.mockImplementation((message: any, origin?) => {
|
|
4711
|
+
expect(message.type).toEqual('portal:meld:searchRetailTransactions')
|
|
4712
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4713
|
+
|
|
4714
|
+
window.dispatchEvent(
|
|
4715
|
+
new MessageEvent('message', {
|
|
4716
|
+
origin: mockHostOrigin,
|
|
4717
|
+
data: { type: 'portal:meld:searchRetailTransactionsResult', data: res },
|
|
4718
|
+
}),
|
|
4719
|
+
)
|
|
4720
|
+
})
|
|
4721
|
+
|
|
4722
|
+
mpc
|
|
4723
|
+
.meldSearchRetailTransactions()
|
|
4724
|
+
.then((data) => {
|
|
4725
|
+
expect(data).toEqual(res)
|
|
4726
|
+
done()
|
|
4727
|
+
})
|
|
4728
|
+
.catch((_) => {
|
|
4729
|
+
expect(0).toEqual(1)
|
|
4730
|
+
done()
|
|
4731
|
+
})
|
|
4732
|
+
})
|
|
4733
|
+
})
|
|
4734
|
+
|
|
4735
|
+
describe('meldGetRetailTransactionBySession', () => {
|
|
4736
|
+
const res = mockMeldGetRetailTransactionResponse
|
|
4737
|
+
|
|
4738
|
+
it('should successfully return a transaction by session ID', (done) => {
|
|
4739
|
+
jest
|
|
4740
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4741
|
+
.mockImplementation((message: any, origin?) => {
|
|
4742
|
+
expect(message.type).toEqual('portal:meld:getRetailTransactionBySession')
|
|
4743
|
+
expect(message.data).toEqual('ses-123')
|
|
4744
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4745
|
+
|
|
4746
|
+
window.dispatchEvent(
|
|
4747
|
+
new MessageEvent('message', {
|
|
4748
|
+
origin: mockHostOrigin,
|
|
4749
|
+
data: { type: 'portal:meld:getRetailTransactionBySessionResult', data: res },
|
|
4750
|
+
}),
|
|
4751
|
+
)
|
|
4752
|
+
})
|
|
4753
|
+
|
|
4754
|
+
mpc
|
|
4755
|
+
.meldGetRetailTransactionBySession('ses-123')
|
|
4756
|
+
.then((data) => {
|
|
4757
|
+
expect(data).toEqual(res)
|
|
4758
|
+
done()
|
|
4759
|
+
})
|
|
4760
|
+
.catch((_) => {
|
|
4761
|
+
expect(0).toEqual(1)
|
|
4762
|
+
done()
|
|
4763
|
+
})
|
|
4764
|
+
})
|
|
4765
|
+
})
|
|
4766
|
+
|
|
4767
|
+
describe('meldGetRetailTransaction', () => {
|
|
4768
|
+
const res = mockMeldGetRetailTransactionResponse
|
|
4769
|
+
|
|
4770
|
+
it('should successfully return a transaction by ID', (done) => {
|
|
4771
|
+
jest
|
|
4772
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4773
|
+
.mockImplementation((message: any, origin?) => {
|
|
4774
|
+
expect(message.type).toEqual('portal:meld:getRetailTransaction')
|
|
4775
|
+
expect(message.data).toEqual('tx-123')
|
|
4776
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4777
|
+
|
|
4778
|
+
window.dispatchEvent(
|
|
4779
|
+
new MessageEvent('message', {
|
|
4780
|
+
origin: mockHostOrigin,
|
|
4781
|
+
data: { type: 'portal:meld:getRetailTransactionResult', data: res },
|
|
4782
|
+
}),
|
|
4783
|
+
)
|
|
4784
|
+
})
|
|
4785
|
+
|
|
4786
|
+
mpc
|
|
4787
|
+
.meldGetRetailTransaction('tx-123')
|
|
4788
|
+
.then((data) => {
|
|
4789
|
+
expect(data).toEqual(res)
|
|
4790
|
+
done()
|
|
4791
|
+
})
|
|
4792
|
+
.catch((_) => {
|
|
4793
|
+
expect(0).toEqual(1)
|
|
4794
|
+
done()
|
|
4795
|
+
})
|
|
4796
|
+
})
|
|
4797
|
+
})
|
|
4798
|
+
|
|
4799
|
+
describe('meldGetServiceProviders', () => {
|
|
4800
|
+
const res = mockMeldDiscoveryResponse
|
|
4801
|
+
|
|
4802
|
+
it('should successfully return service providers without params', (done) => {
|
|
4803
|
+
jest
|
|
4804
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4805
|
+
.mockImplementation((message: any, origin?) => {
|
|
4806
|
+
expect(message.type).toEqual('portal:meld:getServiceProviders')
|
|
4807
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4808
|
+
|
|
4809
|
+
window.dispatchEvent(
|
|
4810
|
+
new MessageEvent('message', {
|
|
4811
|
+
origin: mockHostOrigin,
|
|
4812
|
+
data: { type: 'portal:meld:getServiceProvidersResult', data: res },
|
|
4813
|
+
}),
|
|
4814
|
+
)
|
|
4815
|
+
})
|
|
4816
|
+
|
|
4817
|
+
mpc
|
|
4818
|
+
.meldGetServiceProviders()
|
|
4819
|
+
.then((data) => {
|
|
4820
|
+
expect(data).toEqual(res)
|
|
4821
|
+
done()
|
|
4822
|
+
})
|
|
4823
|
+
.catch((_) => {
|
|
4824
|
+
expect(0).toEqual(1)
|
|
4825
|
+
done()
|
|
4826
|
+
})
|
|
4827
|
+
})
|
|
4828
|
+
|
|
4829
|
+
it('should pass params to the iframe when provided', (done) => {
|
|
4830
|
+
const params = mockMeldDiscoveryParams
|
|
4831
|
+
jest
|
|
4832
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4833
|
+
.mockImplementation((message: any, origin?) => {
|
|
4834
|
+
expect(message.type).toEqual('portal:meld:getServiceProviders')
|
|
4835
|
+
expect(message.data).toMatchObject(params)
|
|
4836
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4837
|
+
|
|
4838
|
+
window.dispatchEvent(
|
|
4839
|
+
new MessageEvent('message', {
|
|
4840
|
+
origin: mockHostOrigin,
|
|
4841
|
+
data: { type: 'portal:meld:getServiceProvidersResult', data: res },
|
|
4842
|
+
}),
|
|
4843
|
+
)
|
|
4844
|
+
})
|
|
4845
|
+
|
|
4846
|
+
mpc
|
|
4847
|
+
.meldGetServiceProviders(params)
|
|
4848
|
+
.then(() => done())
|
|
4849
|
+
.catch((_) => {
|
|
4850
|
+
expect(0).toEqual(1)
|
|
4851
|
+
done()
|
|
4852
|
+
})
|
|
4853
|
+
})
|
|
4854
|
+
})
|
|
4855
|
+
|
|
4856
|
+
describe('meldGetCountries', () => {
|
|
4857
|
+
it('should successfully return countries', (done) => {
|
|
4858
|
+
const res = mockMeldDiscoveryResponse
|
|
4859
|
+
jest
|
|
4860
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4861
|
+
.mockImplementation((message: any, origin?) => {
|
|
4862
|
+
expect(message.type).toEqual('portal:meld:getCountries')
|
|
4863
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4864
|
+
|
|
4865
|
+
window.dispatchEvent(
|
|
4866
|
+
new MessageEvent('message', {
|
|
4867
|
+
origin: mockHostOrigin,
|
|
4868
|
+
data: { type: 'portal:meld:getCountriesResult', data: res },
|
|
4869
|
+
}),
|
|
4870
|
+
)
|
|
4871
|
+
})
|
|
4872
|
+
|
|
4873
|
+
mpc
|
|
4874
|
+
.meldGetCountries()
|
|
4875
|
+
.then((data) => {
|
|
4876
|
+
expect(data).toEqual(res)
|
|
4877
|
+
done()
|
|
4878
|
+
})
|
|
4879
|
+
.catch((_) => {
|
|
4880
|
+
expect(0).toEqual(1)
|
|
4881
|
+
done()
|
|
4882
|
+
})
|
|
4883
|
+
})
|
|
4884
|
+
|
|
4885
|
+
it('should error out if the iframe sends an error message', (done) => {
|
|
4886
|
+
jest
|
|
4887
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4888
|
+
.mockImplementationOnce((_message: any, _origin?) => {
|
|
4889
|
+
window.dispatchEvent(
|
|
4890
|
+
new MessageEvent('message', {
|
|
4891
|
+
origin: mockHostOrigin,
|
|
4892
|
+
data: { type: 'portal:meld:getCountriesError', data: { code: 1, message: 'test' } },
|
|
4893
|
+
}),
|
|
4894
|
+
)
|
|
4895
|
+
})
|
|
4896
|
+
|
|
4897
|
+
mpc
|
|
4898
|
+
.meldGetCountries()
|
|
4899
|
+
.then(() => {
|
|
4900
|
+
expect(0).toEqual(1)
|
|
4901
|
+
done()
|
|
4902
|
+
})
|
|
4903
|
+
.catch((e) => {
|
|
4904
|
+
expect(e).toBeInstanceOf(PortalMpcError)
|
|
4905
|
+
done()
|
|
4906
|
+
})
|
|
4907
|
+
})
|
|
4908
|
+
})
|
|
4909
|
+
|
|
4910
|
+
describe('meldGetFiatCurrencies', () => {
|
|
4911
|
+
it('should successfully return fiat currencies', (done) => {
|
|
4912
|
+
const res = mockMeldDiscoveryResponse
|
|
4913
|
+
jest
|
|
4914
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4915
|
+
.mockImplementation((message: any, origin?) => {
|
|
4916
|
+
expect(message.type).toEqual('portal:meld:getFiatCurrencies')
|
|
4917
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4918
|
+
|
|
4919
|
+
window.dispatchEvent(
|
|
4920
|
+
new MessageEvent('message', {
|
|
4921
|
+
origin: mockHostOrigin,
|
|
4922
|
+
data: { type: 'portal:meld:getFiatCurrenciesResult', data: res },
|
|
4923
|
+
}),
|
|
4924
|
+
)
|
|
4925
|
+
})
|
|
4926
|
+
|
|
4927
|
+
mpc
|
|
4928
|
+
.meldGetFiatCurrencies()
|
|
4929
|
+
.then((data) => {
|
|
4930
|
+
expect(data).toEqual(res)
|
|
4931
|
+
done()
|
|
4932
|
+
})
|
|
4933
|
+
.catch((_) => {
|
|
4934
|
+
expect(0).toEqual(1)
|
|
4935
|
+
done()
|
|
4936
|
+
})
|
|
4937
|
+
})
|
|
4938
|
+
})
|
|
4939
|
+
|
|
4940
|
+
describe('meldGetCryptoCurrencies', () => {
|
|
4941
|
+
it('should successfully return crypto currencies', (done) => {
|
|
4942
|
+
const res = mockMeldDiscoveryResponse
|
|
4943
|
+
jest
|
|
4944
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4945
|
+
.mockImplementation((message: any, origin?) => {
|
|
4946
|
+
expect(message.type).toEqual('portal:meld:getCryptoCurrencies')
|
|
4947
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4948
|
+
|
|
4949
|
+
window.dispatchEvent(
|
|
4950
|
+
new MessageEvent('message', {
|
|
4951
|
+
origin: mockHostOrigin,
|
|
4952
|
+
data: { type: 'portal:meld:getCryptoCurrenciesResult', data: res },
|
|
4953
|
+
}),
|
|
4954
|
+
)
|
|
4955
|
+
})
|
|
4956
|
+
|
|
4957
|
+
mpc.meldGetCryptoCurrencies().then((data) => { expect(data).toEqual(res); done() }).catch((_) => { expect(0).toEqual(1); done() })
|
|
4958
|
+
})
|
|
4959
|
+
})
|
|
4960
|
+
|
|
4961
|
+
describe('meldGetPaymentMethods', () => {
|
|
4962
|
+
it('should successfully return payment methods', (done) => {
|
|
4963
|
+
const res = mockMeldDiscoveryResponse
|
|
4964
|
+
jest
|
|
4965
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4966
|
+
.mockImplementation((message: any, origin?) => {
|
|
4967
|
+
expect(message.type).toEqual('portal:meld:getPaymentMethods')
|
|
4968
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4969
|
+
|
|
4970
|
+
window.dispatchEvent(
|
|
4971
|
+
new MessageEvent('message', {
|
|
4972
|
+
origin: mockHostOrigin,
|
|
4973
|
+
data: { type: 'portal:meld:getPaymentMethodsResult', data: res },
|
|
4974
|
+
}),
|
|
4975
|
+
)
|
|
4976
|
+
})
|
|
4977
|
+
|
|
4978
|
+
mpc.meldGetPaymentMethods().then((data) => { expect(data).toEqual(res); done() }).catch((_) => { expect(0).toEqual(1); done() })
|
|
4979
|
+
})
|
|
4980
|
+
})
|
|
4981
|
+
|
|
4982
|
+
describe('meldGetDefaults', () => {
|
|
4983
|
+
it('should successfully return defaults', (done) => {
|
|
4984
|
+
const res = mockMeldDiscoveryResponse
|
|
4985
|
+
jest
|
|
4986
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
4987
|
+
.mockImplementation((message: any, origin?) => {
|
|
4988
|
+
expect(message.type).toEqual('portal:meld:getDefaults')
|
|
4989
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
4990
|
+
|
|
4991
|
+
window.dispatchEvent(
|
|
4992
|
+
new MessageEvent('message', {
|
|
4993
|
+
origin: mockHostOrigin,
|
|
4994
|
+
data: { type: 'portal:meld:getDefaultsResult', data: res },
|
|
4995
|
+
}),
|
|
4996
|
+
)
|
|
4997
|
+
})
|
|
4998
|
+
|
|
4999
|
+
mpc.meldGetDefaults().then((data) => { expect(data).toEqual(res); done() }).catch((_) => { expect(0).toEqual(1); done() })
|
|
5000
|
+
})
|
|
5001
|
+
})
|
|
5002
|
+
|
|
5003
|
+
describe('meldGetBuyLimits', () => {
|
|
5004
|
+
it('should successfully return buy limits', (done) => {
|
|
5005
|
+
const res = mockMeldDiscoveryResponse
|
|
5006
|
+
jest
|
|
5007
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
5008
|
+
.mockImplementation((message: any, origin?) => {
|
|
5009
|
+
expect(message.type).toEqual('portal:meld:getBuyLimits')
|
|
5010
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
5011
|
+
|
|
5012
|
+
window.dispatchEvent(
|
|
5013
|
+
new MessageEvent('message', {
|
|
5014
|
+
origin: mockHostOrigin,
|
|
5015
|
+
data: { type: 'portal:meld:getBuyLimitsResult', data: res },
|
|
5016
|
+
}),
|
|
5017
|
+
)
|
|
5018
|
+
})
|
|
5019
|
+
|
|
5020
|
+
mpc.meldGetBuyLimits().then((data) => { expect(data).toEqual(res); done() }).catch((_) => { expect(0).toEqual(1); done() })
|
|
5021
|
+
})
|
|
5022
|
+
})
|
|
5023
|
+
|
|
5024
|
+
describe('meldGetSellLimits', () => {
|
|
5025
|
+
it('should successfully return sell limits', (done) => {
|
|
5026
|
+
const res = mockMeldDiscoveryResponse
|
|
5027
|
+
jest
|
|
5028
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
5029
|
+
.mockImplementation((message: any, origin?) => {
|
|
5030
|
+
expect(message.type).toEqual('portal:meld:getSellLimits')
|
|
5031
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
5032
|
+
|
|
5033
|
+
window.dispatchEvent(
|
|
5034
|
+
new MessageEvent('message', {
|
|
5035
|
+
origin: mockHostOrigin,
|
|
5036
|
+
data: { type: 'portal:meld:getSellLimitsResult', data: res },
|
|
5037
|
+
}),
|
|
5038
|
+
)
|
|
5039
|
+
})
|
|
5040
|
+
|
|
5041
|
+
mpc.meldGetSellLimits().then((data) => { expect(data).toEqual(res); done() }).catch((_) => { expect(0).toEqual(1); done() })
|
|
5042
|
+
})
|
|
5043
|
+
})
|
|
5044
|
+
|
|
5045
|
+
describe('meldGetKycLimits', () => {
|
|
5046
|
+
it('should successfully return KYC limits', (done) => {
|
|
5047
|
+
const res = mockMeldDiscoveryResponse
|
|
5048
|
+
jest
|
|
5049
|
+
.spyOn(mpc.iframe?.contentWindow!, 'postMessage')
|
|
5050
|
+
.mockImplementation((message: any, origin?) => {
|
|
5051
|
+
expect(message.type).toEqual('portal:meld:getKycLimits')
|
|
5052
|
+
expect(origin).toEqual(mockHostOrigin)
|
|
5053
|
+
|
|
5054
|
+
window.dispatchEvent(
|
|
5055
|
+
new MessageEvent('message', {
|
|
5056
|
+
origin: mockHostOrigin,
|
|
5057
|
+
data: { type: 'portal:meld:getKycLimitsResult', data: res },
|
|
5058
|
+
}),
|
|
5059
|
+
)
|
|
5060
|
+
})
|
|
5061
|
+
|
|
5062
|
+
mpc.meldGetKycLimits().then((data) => { expect(data).toEqual(res); done() }).catch((_) => { expect(0).toEqual(1); done() })
|
|
5063
|
+
})
|
|
5064
|
+
})
|
|
5065
|
+
|
|
4455
5066
|
describe('accountAbstractionBuildBatchedUserOp', () => {
|
|
4456
5067
|
const args = mockBuildBatchedUserOpRequest
|
|
4457
5068
|
const res = mockBuildBatchedUserOpResponse
|
|
@@ -4540,9 +5151,7 @@ describe('Mpc', () => {
|
|
|
4540
5151
|
.mockImplementation((message: any, origin?) => {
|
|
4541
5152
|
const { type, data } = message
|
|
4542
5153
|
|
|
4543
|
-
expect(type).toEqual(
|
|
4544
|
-
'portal:accountAbstraction:broadcastBatchedUserOp',
|
|
4545
|
-
)
|
|
5154
|
+
expect(type).toEqual('portal:accountAbstraction:broadcastBatchedUserOp')
|
|
4546
5155
|
expect(data).toMatchObject(args)
|
|
4547
5156
|
expect(typeof message.traceId).toBe('string')
|
|
4548
5157
|
expect(origin).toEqual(mockHostOrigin)
|
|
@@ -4576,9 +5185,7 @@ describe('Mpc', () => {
|
|
|
4576
5185
|
.mockImplementationOnce((message: any, origin?) => {
|
|
4577
5186
|
const { type, data } = message
|
|
4578
5187
|
|
|
4579
|
-
expect(type).toEqual(
|
|
4580
|
-
'portal:accountAbstraction:broadcastBatchedUserOp',
|
|
4581
|
-
)
|
|
5188
|
+
expect(type).toEqual('portal:accountAbstraction:broadcastBatchedUserOp')
|
|
4582
5189
|
expect(data).toMatchObject(args)
|
|
4583
5190
|
expect(typeof message.traceId).toBe('string')
|
|
4584
5191
|
expect(origin).toEqual(mockHostOrigin)
|
|
@@ -4611,4 +5218,194 @@ describe('Mpc', () => {
|
|
|
4611
5218
|
})
|
|
4612
5219
|
})
|
|
4613
5220
|
})
|
|
4614
|
-
|
|
5221
|
+
|
|
5222
|
+
|
|
5223
|
+
describe('walletNotOnDevice detection', () => {
|
|
5224
|
+
const makeClient = (overrides: Record<string, any> = {}) => ({
|
|
5225
|
+
id: 'client-test',
|
|
5226
|
+
address: mockAddress,
|
|
5227
|
+
ejectedAt: null as string | null,
|
|
5228
|
+
custodian: { id: 'c', name: 'c' },
|
|
5229
|
+
environment: { id: 'e', name: 'e', backupWithPortalEnabled: false, isMultiBackupEnabled: false },
|
|
5230
|
+
isAccountAbstracted: false,
|
|
5231
|
+
metadata: { namespaces: {} },
|
|
5232
|
+
wallets: [] as any[],
|
|
5233
|
+
...overrides,
|
|
5234
|
+
})
|
|
5235
|
+
|
|
5236
|
+
const makeWallet = (
|
|
5237
|
+
curve: PortalCurve,
|
|
5238
|
+
signingStatus: string,
|
|
5239
|
+
backupStatus: string,
|
|
5240
|
+
) => ({
|
|
5241
|
+
id: `wallet-${curve}`,
|
|
5242
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
5243
|
+
curve,
|
|
5244
|
+
publicKey: 'pk',
|
|
5245
|
+
signingSharePairs: [{ id: 'sp1', createdAt: '2024-01-01T00:00:00.000Z', status: signingStatus }],
|
|
5246
|
+
backupSharePairs: [
|
|
5247
|
+
{
|
|
5248
|
+
id: 'bp1',
|
|
5249
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
5250
|
+
backupMethod: BackupMethods.password,
|
|
5251
|
+
status: backupStatus,
|
|
5252
|
+
},
|
|
5253
|
+
],
|
|
5254
|
+
})
|
|
5255
|
+
|
|
5256
|
+
const dispatchReady = () => {
|
|
5257
|
+
window.dispatchEvent(
|
|
5258
|
+
new MessageEvent('message', {
|
|
5259
|
+
origin: `https://${mockHost}`,
|
|
5260
|
+
data: { type: 'portal:ready', data: true },
|
|
5261
|
+
}),
|
|
5262
|
+
)
|
|
5263
|
+
}
|
|
5264
|
+
|
|
5265
|
+
const flushPromises = () => new Promise<void>((resolve) => setTimeout(resolve, 0))
|
|
5266
|
+
|
|
5267
|
+
beforeEach(() => {
|
|
5268
|
+
jest.spyOn(mpc, 'getAddress').mockResolvedValue(mockAddress)
|
|
5269
|
+
;(mpc as any).waitForReadyMessage()
|
|
5270
|
+
})
|
|
5271
|
+
|
|
5272
|
+
it('does not emit when client has no wallets (new user / initial setup)', async () => {
|
|
5273
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(makeClient({ wallets: [] }) as any)
|
|
5274
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false })
|
|
5275
|
+
|
|
5276
|
+
dispatchReady()
|
|
5277
|
+
await flushPromises()
|
|
5278
|
+
|
|
5279
|
+
expect(portalMock.triggerWalletNotOnDevice).not.toHaveBeenCalled()
|
|
5280
|
+
expect(portalMock.triggerReady).toHaveBeenCalled()
|
|
5281
|
+
})
|
|
5282
|
+
|
|
5283
|
+
it('does not emit when wallets exist but all signing share pairs are incomplete (setup in progress)', async () => {
|
|
5284
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5285
|
+
makeClient({
|
|
5286
|
+
wallets: [
|
|
5287
|
+
makeWallet(PortalCurve.SECP256K1, 'incomplete', 'incomplete'),
|
|
5288
|
+
makeWallet(PortalCurve.ED25519, 'incomplete', 'incomplete'),
|
|
5289
|
+
],
|
|
5290
|
+
}) as any,
|
|
5291
|
+
)
|
|
5292
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false })
|
|
5293
|
+
|
|
5294
|
+
dispatchReady()
|
|
5295
|
+
await flushPromises()
|
|
5296
|
+
|
|
5297
|
+
expect(portalMock.triggerWalletNotOnDevice).not.toHaveBeenCalled()
|
|
5298
|
+
expect(portalMock.triggerReady).toHaveBeenCalled()
|
|
5299
|
+
})
|
|
5300
|
+
|
|
5301
|
+
it('does not emit when wallet is present on device', async () => {
|
|
5302
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5303
|
+
makeClient({
|
|
5304
|
+
wallets: [
|
|
5305
|
+
makeWallet(PortalCurve.SECP256K1, 'completed', 'completed'),
|
|
5306
|
+
makeWallet(PortalCurve.ED25519, 'completed', 'completed'),
|
|
5307
|
+
],
|
|
5308
|
+
}) as any,
|
|
5309
|
+
)
|
|
5310
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: true, ED25519: true })
|
|
5311
|
+
|
|
5312
|
+
dispatchReady()
|
|
5313
|
+
await flushPromises()
|
|
5314
|
+
|
|
5315
|
+
expect(portalMock.triggerWalletNotOnDevice).not.toHaveBeenCalled()
|
|
5316
|
+
})
|
|
5317
|
+
|
|
5318
|
+
it('emits walletNotOnDevice with isBackedUp=false when wallet is not on device and not backed up', async () => {
|
|
5319
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5320
|
+
makeClient({
|
|
5321
|
+
wallets: [
|
|
5322
|
+
makeWallet(PortalCurve.SECP256K1, 'completed', 'incomplete'),
|
|
5323
|
+
makeWallet(PortalCurve.ED25519, 'completed', 'incomplete'),
|
|
5324
|
+
],
|
|
5325
|
+
}) as any,
|
|
5326
|
+
)
|
|
5327
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false })
|
|
5328
|
+
|
|
5329
|
+
dispatchReady()
|
|
5330
|
+
await flushPromises()
|
|
5331
|
+
|
|
5332
|
+
expect(portalMock.triggerWalletNotOnDevice).toHaveBeenCalledWith({
|
|
5333
|
+
clientId: 'client-test',
|
|
5334
|
+
isBackedUp: false,
|
|
5335
|
+
reason: 'storage_cleared',
|
|
5336
|
+
})
|
|
5337
|
+
})
|
|
5338
|
+
|
|
5339
|
+
it('emits walletNotOnDevice with isBackedUp=true when at least one backup is complete', async () => {
|
|
5340
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5341
|
+
makeClient({
|
|
5342
|
+
wallets: [makeWallet(PortalCurve.SECP256K1, 'completed', 'completed')],
|
|
5343
|
+
}) as any,
|
|
5344
|
+
)
|
|
5345
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false })
|
|
5346
|
+
|
|
5347
|
+
dispatchReady()
|
|
5348
|
+
await flushPromises()
|
|
5349
|
+
|
|
5350
|
+
expect(portalMock.triggerWalletNotOnDevice).toHaveBeenCalledWith({
|
|
5351
|
+
clientId: 'client-test',
|
|
5352
|
+
isBackedUp: true,
|
|
5353
|
+
reason: 'storage_cleared',
|
|
5354
|
+
})
|
|
5355
|
+
})
|
|
5356
|
+
|
|
5357
|
+
it('does not emit for EVM-only client when SECP256K1 share is present (ED25519 absence is irrelevant)', async () => {
|
|
5358
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5359
|
+
makeClient({
|
|
5360
|
+
wallets: [makeWallet(PortalCurve.SECP256K1, 'completed', 'incomplete')],
|
|
5361
|
+
}) as any,
|
|
5362
|
+
)
|
|
5363
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: true, ED25519: false })
|
|
5364
|
+
|
|
5365
|
+
dispatchReady()
|
|
5366
|
+
await flushPromises()
|
|
5367
|
+
|
|
5368
|
+
expect(portalMock.triggerWalletNotOnDevice).not.toHaveBeenCalled()
|
|
5369
|
+
})
|
|
5370
|
+
|
|
5371
|
+
it('emits for EVM-only client when SECP256K1 share is missing', async () => {
|
|
5372
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5373
|
+
makeClient({
|
|
5374
|
+
wallets: [makeWallet(PortalCurve.SECP256K1, 'completed', 'incomplete')],
|
|
5375
|
+
}) as any,
|
|
5376
|
+
)
|
|
5377
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false })
|
|
5378
|
+
|
|
5379
|
+
dispatchReady()
|
|
5380
|
+
await flushPromises()
|
|
5381
|
+
|
|
5382
|
+
expect(portalMock.triggerWalletNotOnDevice).toHaveBeenCalled()
|
|
5383
|
+
})
|
|
5384
|
+
|
|
5385
|
+
it('does not emit when wallet is ejected (recovery is impossible)', async () => {
|
|
5386
|
+
jest.spyOn(mpc, 'getClient').mockResolvedValue(
|
|
5387
|
+
makeClient({
|
|
5388
|
+
ejectedAt: '2024-06-01T00:00:00.000Z',
|
|
5389
|
+
wallets: [makeWallet(PortalCurve.SECP256K1, 'completed', 'incomplete')],
|
|
5390
|
+
}) as any,
|
|
5391
|
+
)
|
|
5392
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockResolvedValue({ SECP256K1: false, ED25519: false })
|
|
5393
|
+
|
|
5394
|
+
dispatchReady()
|
|
5395
|
+
await flushPromises()
|
|
5396
|
+
|
|
5397
|
+
expect(portalMock.triggerWalletNotOnDevice).not.toHaveBeenCalled()
|
|
5398
|
+
})
|
|
5399
|
+
|
|
5400
|
+
it('still calls triggerReady when detection throws (detection must not block initialization)', async () => {
|
|
5401
|
+
jest.spyOn(mpc, 'getClient').mockRejectedValue(new Error('network error'))
|
|
5402
|
+
jest.spyOn(mpc, 'checkSharesOnDevice').mockRejectedValue(new Error('network error'))
|
|
5403
|
+
|
|
5404
|
+
dispatchReady()
|
|
5405
|
+
await flushPromises()
|
|
5406
|
+
|
|
5407
|
+
expect(portalMock.triggerWalletNotOnDevice).not.toHaveBeenCalled()
|
|
5408
|
+
expect(portalMock.triggerReady).toHaveBeenCalled()
|
|
5409
|
+
})
|
|
5410
|
+
})
|
|
5411
|
+
})
|