@portal-hq/web 3.12.0 → 3.13.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.
- package/lib/commonjs/index.js +16 -5
- package/lib/commonjs/index.test.js +1 -1
- package/lib/commonjs/integrations/ramps/index.js +12 -0
- package/lib/commonjs/integrations/ramps/noah/index.js +75 -0
- package/lib/commonjs/integrations/ramps/noah/index.test.js +156 -0
- package/lib/commonjs/mpc/index.js +95 -1
- package/lib/commonjs/shared/types/index.js +1 -0
- package/lib/commonjs/shared/types/noah.js +2 -0
- package/lib/esm/index.js +16 -5
- package/lib/esm/index.test.js +1 -1
- package/lib/esm/integrations/ramps/index.js +6 -0
- package/lib/esm/integrations/ramps/noah/index.js +72 -0
- package/lib/esm/integrations/ramps/noah/index.test.js +151 -0
- package/lib/esm/mpc/index.js +95 -1
- package/lib/esm/shared/types/index.js +1 -0
- package/lib/esm/shared/types/noah.js +1 -0
- package/noah-types.d.ts +28 -0
- package/package.json +4 -2
- package/src/index.test.ts +1 -1
- package/src/index.ts +46 -6
- package/src/integrations/ramps/index.ts +10 -0
- package/src/integrations/ramps/noah/index.test.ts +159 -0
- package/src/integrations/ramps/noah/index.ts +89 -0
- package/src/mpc/index.ts +115 -1
- package/src/shared/types/index.ts +1 -0
- package/src/shared/types/noah.ts +150 -0
- package/tsconfig.json +1 -0
package/lib/commonjs/index.js
CHANGED
|
@@ -41,6 +41,7 @@ const mpc_1 = __importDefault(require("./mpc"));
|
|
|
41
41
|
const provider_1 = __importStar(require("./provider"));
|
|
42
42
|
const yield_1 = __importDefault(require("./integrations/yield"));
|
|
43
43
|
const trading_1 = __importDefault(require("./integrations/trading"));
|
|
44
|
+
const ramps_1 = __importDefault(require("./integrations/ramps"));
|
|
44
45
|
const security_1 = __importDefault(require("./integrations/security"));
|
|
45
46
|
const delegations_1 = __importDefault(require("./integrations/delegations"));
|
|
46
47
|
const passkeys_1 = __importDefault(require("./passkeys"));
|
|
@@ -95,6 +96,7 @@ class Portal {
|
|
|
95
96
|
portal: this,
|
|
96
97
|
});
|
|
97
98
|
this.yield = new yield_1.default({ mpc: this.mpc });
|
|
99
|
+
this.ramps = new ramps_1.default({ mpc: this.mpc });
|
|
98
100
|
this.trading = new trading_1.default({ mpc: this.mpc });
|
|
99
101
|
this.security = new security_1.default({ mpc: this.mpc });
|
|
100
102
|
this.delegations = new delegations_1.default({ mpc: this.mpc });
|
|
@@ -697,6 +699,10 @@ class Portal {
|
|
|
697
699
|
return response;
|
|
698
700
|
});
|
|
699
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* Build, sign, and broadcast a native SOL transfer on the given Solana CAIP-2 `chainId`.
|
|
704
|
+
* `to` must be a valid Solana public key (base58); `lamports` must be a positive integer.
|
|
705
|
+
*/
|
|
700
706
|
sendSol({ chainId, to, lamports, }) {
|
|
701
707
|
var _a;
|
|
702
708
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -704,9 +710,16 @@ class Portal {
|
|
|
704
710
|
if (!chainId.startsWith('solana:')) {
|
|
705
711
|
throw new Error('[Portal] Invalid chainId. Please provide a chainId that starts with "solana:"');
|
|
706
712
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
713
|
+
if (!to || typeof to !== 'string') {
|
|
714
|
+
throw new Error('[Portal] Invalid "to" Solana address provided');
|
|
715
|
+
}
|
|
716
|
+
const toTrimmed = to.trim();
|
|
717
|
+
let toPublicKey;
|
|
718
|
+
try {
|
|
719
|
+
toPublicKey = new web3_js_1.PublicKey(toTrimmed);
|
|
720
|
+
}
|
|
721
|
+
catch (_b) {
|
|
722
|
+
throw new Error('[Portal] Invalid "to" Solana address provided (not a valid public key)');
|
|
710
723
|
}
|
|
711
724
|
// Validate the lamports.
|
|
712
725
|
if (typeof lamports !== 'number' || lamports <= 0) {
|
|
@@ -737,8 +750,6 @@ class Portal {
|
|
|
737
750
|
new web3_js_1.Connection(gatewayUrl, 'confirmed');
|
|
738
751
|
// The sender's public key.
|
|
739
752
|
const fromPublicKey = new web3_js_1.PublicKey(solanaAddress);
|
|
740
|
-
// The recipient's public key.
|
|
741
|
-
const toPublicKey = new web3_js_1.PublicKey(to);
|
|
742
753
|
// Create a new transaction.
|
|
743
754
|
const transaction = new web3_js_1.Transaction().add(web3_js_1.SystemProgram.transfer({
|
|
744
755
|
fromPubkey: fromPublicKey,
|
|
@@ -542,7 +542,7 @@ describe('Portal', () => {
|
|
|
542
542
|
chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
543
543
|
to: 'test',
|
|
544
544
|
lamports: 10000,
|
|
545
|
-
})).rejects.toThrow(new Error('[Portal] Invalid "to" Solana address provided
|
|
545
|
+
})).rejects.toThrow(new Error('[Portal] Invalid "to" Solana address provided (not a valid public key)'));
|
|
546
546
|
}));
|
|
547
547
|
it('should throw an error if the lamports arg is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
548
548
|
yield expect(portal.sendSol({
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const noah_1 = __importDefault(require("./noah"));
|
|
7
|
+
class Ramps {
|
|
8
|
+
constructor({ mpc }) {
|
|
9
|
+
this.noah = new noah_1.default({ mpc });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.default = Ramps;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
/**
|
|
13
|
+
* Noah fiat on/off-ramp API on `portal.ramps.noah`.
|
|
14
|
+
* Each method forwards to the embedded Portal iframe, which calls connect-api.
|
|
15
|
+
*/
|
|
16
|
+
class Noah {
|
|
17
|
+
constructor({ mpc }) {
|
|
18
|
+
this.mpc = mpc;
|
|
19
|
+
}
|
|
20
|
+
/** Start hosted KYC; response includes `hostedUrl` to open in a browser tab. */
|
|
21
|
+
initiateKyc(data) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
return this.mpc.initiateKyc(data);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Create a pay-in (fiat → crypto) with bank transfer instructions. */
|
|
27
|
+
initiatePayin(data) {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
return this.mpc.initiatePayin(data);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Dry-run pay-in pricing / eligibility for a payment method and fiat amount. */
|
|
33
|
+
simulatePayin(data) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
return this.mpc.simulatePayin(data);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Countries supported for fiat payouts. */
|
|
39
|
+
getPayoutCountries() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
return this.mpc.getPayoutCountries();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** Available payout rails for a country / currency pair. */
|
|
45
|
+
getPayoutChannels(data) {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
return this.mpc.getPayoutChannels(data);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Dynamic form schema for a payout channel (recipient fields). */
|
|
51
|
+
getPayoutChannelForm(channelId) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
return this.mpc.getPayoutChannelForm(channelId);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/** Quote fees and crypto amount for a payout channel and form payload. */
|
|
57
|
+
getPayoutQuote(data) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
return this.mpc.getPayoutQuote(data);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Start payout execution; may return on-chain deposit `conditions` for crypto legs. */
|
|
63
|
+
initiatePayout(data) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
return this.mpc.initiatePayout(data);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Pay-in payment methods available to the customer. */
|
|
69
|
+
getPaymentMethods() {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
return this.mpc.getPaymentMethods();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.default = Noah;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @jest-environment jsdom
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const mpc_1 = __importDefault(require("../../../mpc"));
|
|
19
|
+
const _1 = __importDefault(require("."));
|
|
20
|
+
const portal_1 = __importDefault(require("../../../__mocks/portal/portal"));
|
|
21
|
+
const constants_1 = require("../../../__mocks/constants");
|
|
22
|
+
const TRUSTED_KYC_HOST = 'kyc.example';
|
|
23
|
+
const openTrustedUrl = (url) => {
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = new URL(url);
|
|
27
|
+
}
|
|
28
|
+
catch (_a) {
|
|
29
|
+
throw new Error('Invalid hostedUrl');
|
|
30
|
+
}
|
|
31
|
+
if (parsed.protocol !== 'https:' || parsed.hostname !== TRUSTED_KYC_HOST) {
|
|
32
|
+
throw new Error('Untrusted hostedUrl origin');
|
|
33
|
+
}
|
|
34
|
+
return window.open(parsed.toString(), '_blank', 'noopener,noreferrer');
|
|
35
|
+
};
|
|
36
|
+
describe('Noah', () => {
|
|
37
|
+
let mpc;
|
|
38
|
+
let noah;
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
jest.clearAllMocks();
|
|
41
|
+
portal_1.default.host = constants_1.mockHost;
|
|
42
|
+
mpc = new mpc_1.default({
|
|
43
|
+
portal: portal_1.default,
|
|
44
|
+
});
|
|
45
|
+
noah = new _1.default({ mpc });
|
|
46
|
+
});
|
|
47
|
+
it('should call mpc.initiateKyc with the request', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
const spy = jest.spyOn(mpc, 'initiateKyc').mockResolvedValue({
|
|
49
|
+
data: {
|
|
50
|
+
hostedUrl: 'https://kyc.example',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
const openSpy = jest.spyOn(window, 'open').mockImplementation(() => null);
|
|
54
|
+
const body = { returnUrl: 'https://app.example/cb' };
|
|
55
|
+
const result = yield noah.initiateKyc(body);
|
|
56
|
+
expect(spy).toHaveBeenCalledWith(body);
|
|
57
|
+
expect(result.data.hostedUrl).toBe('https://kyc.example');
|
|
58
|
+
openTrustedUrl(result.data.hostedUrl);
|
|
59
|
+
expect(openSpy).toHaveBeenCalledWith('https://kyc.example/', '_blank', 'noopener,noreferrer');
|
|
60
|
+
openSpy.mockRestore();
|
|
61
|
+
}));
|
|
62
|
+
it('should call mpc.initiatePayin', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
+
const req = {
|
|
64
|
+
fiatCurrency: 'USD',
|
|
65
|
+
cryptoCurrency: 'USDC_TEST',
|
|
66
|
+
network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
|
|
67
|
+
destinationAddress: 'SoLAddr1111111111111111111111111111111111111',
|
|
68
|
+
};
|
|
69
|
+
const spy = jest.spyOn(mpc, 'initiatePayin').mockResolvedValue({
|
|
70
|
+
data: { payinId: 'p1', bankDetails: {} },
|
|
71
|
+
});
|
|
72
|
+
yield noah.initiatePayin(req);
|
|
73
|
+
expect(spy).toHaveBeenCalledWith(req);
|
|
74
|
+
}));
|
|
75
|
+
it('should call mpc.simulatePayin with sandbox body', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
+
const sim = {
|
|
77
|
+
paymentMethodId: 'pm-1',
|
|
78
|
+
fiatAmount: '10',
|
|
79
|
+
fiatCurrency: 'USD',
|
|
80
|
+
};
|
|
81
|
+
const spy = jest.spyOn(mpc, 'simulatePayin').mockResolvedValue({
|
|
82
|
+
data: {},
|
|
83
|
+
});
|
|
84
|
+
yield noah.simulatePayin(sim);
|
|
85
|
+
expect(spy).toHaveBeenCalledWith(sim);
|
|
86
|
+
}));
|
|
87
|
+
it('should call mpc.getPayoutCountries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
+
const spy = jest.spyOn(mpc, 'getPayoutCountries').mockResolvedValue({
|
|
89
|
+
data: { countries: [] },
|
|
90
|
+
});
|
|
91
|
+
yield noah.getPayoutCountries();
|
|
92
|
+
expect(spy).toHaveBeenCalled();
|
|
93
|
+
}));
|
|
94
|
+
it('should call mpc.getPayoutChannels', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
|
+
const req = {
|
|
96
|
+
country: 'US',
|
|
97
|
+
cryptoCurrency: 'USDC_TEST',
|
|
98
|
+
fiatCurrency: 'USD',
|
|
99
|
+
fiatAmount: '10',
|
|
100
|
+
};
|
|
101
|
+
const spy = jest.spyOn(mpc, 'getPayoutChannels').mockResolvedValue({
|
|
102
|
+
data: [],
|
|
103
|
+
});
|
|
104
|
+
yield noah.getPayoutChannels(req);
|
|
105
|
+
expect(spy).toHaveBeenCalledWith(req);
|
|
106
|
+
}));
|
|
107
|
+
it('should call mpc.getPayoutChannelForm', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
108
|
+
const spy = jest
|
|
109
|
+
.spyOn(mpc, 'getPayoutChannelForm')
|
|
110
|
+
.mockResolvedValue({ data: {} });
|
|
111
|
+
yield noah.getPayoutChannelForm('ch-1');
|
|
112
|
+
expect(spy).toHaveBeenCalledWith('ch-1');
|
|
113
|
+
}));
|
|
114
|
+
it('should call mpc.getPayoutQuote', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
115
|
+
const req = {
|
|
116
|
+
channelId: 'ch-1',
|
|
117
|
+
cryptoCurrency: 'USDC_TEST',
|
|
118
|
+
fiatAmount: '10',
|
|
119
|
+
};
|
|
120
|
+
const spy = jest.spyOn(mpc, 'getPayoutQuote').mockResolvedValue({
|
|
121
|
+
data: {
|
|
122
|
+
payoutId: 'out-1',
|
|
123
|
+
formSessionId: 'fs-1',
|
|
124
|
+
cryptoAmountEstimate: '10',
|
|
125
|
+
totalFee: '0.01',
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
yield noah.getPayoutQuote(req);
|
|
129
|
+
expect(spy).toHaveBeenCalledWith(req);
|
|
130
|
+
}));
|
|
131
|
+
it('should call mpc.initiatePayout', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
|
+
const expiry = new Date(Date.now() + 24 * 60 * 60 * 1000)
|
|
133
|
+
.toISOString()
|
|
134
|
+
.replace(/\.\d{3}Z$/, 'Z');
|
|
135
|
+
const nonce = `nonce-${Date.now()}-${Math.floor(Math.random() * 1e9)}`;
|
|
136
|
+
const req = {
|
|
137
|
+
payoutId: 'p1',
|
|
138
|
+
sourceAddress: 'SoLAddr1111111111111111111111111111111111111',
|
|
139
|
+
expiry,
|
|
140
|
+
nonce,
|
|
141
|
+
network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
|
|
142
|
+
};
|
|
143
|
+
const spy = jest.spyOn(mpc, 'initiatePayout').mockResolvedValue({
|
|
144
|
+
data: { destinationAddress: 'dest', conditions: [] },
|
|
145
|
+
});
|
|
146
|
+
yield noah.initiatePayout(req);
|
|
147
|
+
expect(spy).toHaveBeenCalledWith(req);
|
|
148
|
+
}));
|
|
149
|
+
it('should call mpc.getPaymentMethods', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
150
|
+
const spy = jest.spyOn(mpc, 'getPaymentMethods').mockResolvedValue({
|
|
151
|
+
data: { paymentMethods: [] },
|
|
152
|
+
});
|
|
153
|
+
yield noah.getPaymentMethods();
|
|
154
|
+
expect(spy).toHaveBeenCalled();
|
|
155
|
+
}));
|
|
156
|
+
});
|
|
@@ -14,7 +14,7 @@ const errors_1 = require("./errors");
|
|
|
14
14
|
const logger_1 = require("../logger");
|
|
15
15
|
const index_1 = require("../index");
|
|
16
16
|
const trace_1 = require("../shared/trace");
|
|
17
|
-
const WEB_SDK_VERSION = '3.
|
|
17
|
+
const WEB_SDK_VERSION = '3.13.0-alpha.0';
|
|
18
18
|
class Mpc {
|
|
19
19
|
get ready() {
|
|
20
20
|
return this._ready;
|
|
@@ -518,6 +518,100 @@ class Mpc {
|
|
|
518
518
|
});
|
|
519
519
|
});
|
|
520
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* Noah ramp: postMessage bridge to the Portal iframe (connect-api).
|
|
523
|
+
* Application code should call `portal.ramps.noah` instead of Mpc directly.
|
|
524
|
+
*/
|
|
525
|
+
initiateKyc(data) {
|
|
526
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
527
|
+
return this.handleRequestToIframeAndPost({
|
|
528
|
+
methodMessage: 'portal:noah:initiateKyc',
|
|
529
|
+
errorMessage: 'portal:noah:initiateKycError',
|
|
530
|
+
resultMessage: 'portal:noah:initiateKycResult',
|
|
531
|
+
data,
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
initiatePayin(data) {
|
|
536
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
537
|
+
return this.handleRequestToIframeAndPost({
|
|
538
|
+
methodMessage: 'portal:noah:initiatePayin',
|
|
539
|
+
errorMessage: 'portal:noah:initiatePayinError',
|
|
540
|
+
resultMessage: 'portal:noah:initiatePayinResult',
|
|
541
|
+
data,
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
simulatePayin(data) {
|
|
546
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
547
|
+
return this.handleRequestToIframeAndPost({
|
|
548
|
+
methodMessage: 'portal:noah:simulatePayin',
|
|
549
|
+
errorMessage: 'portal:noah:simulatePayinError',
|
|
550
|
+
resultMessage: 'portal:noah:simulatePayinResult',
|
|
551
|
+
data,
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
getPayoutCountries() {
|
|
556
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
557
|
+
return this.handleRequestToIframeAndPost({
|
|
558
|
+
methodMessage: 'portal:noah:getPayoutCountries',
|
|
559
|
+
errorMessage: 'portal:noah:getPayoutCountriesError',
|
|
560
|
+
resultMessage: 'portal:noah:getPayoutCountriesResult',
|
|
561
|
+
data: {},
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
getPayoutChannels(data) {
|
|
566
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
567
|
+
return this.handleRequestToIframeAndPost({
|
|
568
|
+
methodMessage: 'portal:noah:getPayoutChannels',
|
|
569
|
+
errorMessage: 'portal:noah:getPayoutChannelsError',
|
|
570
|
+
resultMessage: 'portal:noah:getPayoutChannelsResult',
|
|
571
|
+
data,
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
getPayoutChannelForm(channelId) {
|
|
576
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
577
|
+
return this.handleRequestToIframeAndPost({
|
|
578
|
+
methodMessage: 'portal:noah:getPayoutChannelForm',
|
|
579
|
+
errorMessage: 'portal:noah:getPayoutChannelFormError',
|
|
580
|
+
resultMessage: 'portal:noah:getPayoutChannelFormResult',
|
|
581
|
+
data: channelId,
|
|
582
|
+
});
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
getPayoutQuote(data) {
|
|
586
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
587
|
+
return this.handleRequestToIframeAndPost({
|
|
588
|
+
methodMessage: 'portal:noah:getPayoutQuote',
|
|
589
|
+
errorMessage: 'portal:noah:getPayoutQuoteError',
|
|
590
|
+
resultMessage: 'portal:noah:getPayoutQuoteResult',
|
|
591
|
+
data,
|
|
592
|
+
});
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
initiatePayout(data) {
|
|
596
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
597
|
+
return this.handleRequestToIframeAndPost({
|
|
598
|
+
methodMessage: 'portal:noah:initiatePayout',
|
|
599
|
+
errorMessage: 'portal:noah:initiatePayoutError',
|
|
600
|
+
resultMessage: 'portal:noah:initiatePayoutResult',
|
|
601
|
+
data,
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
getPaymentMethods() {
|
|
606
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
607
|
+
return this.handleRequestToIframeAndPost({
|
|
608
|
+
methodMessage: 'portal:noah:getPaymentMethods',
|
|
609
|
+
errorMessage: 'portal:noah:getPaymentMethodsError',
|
|
610
|
+
resultMessage: 'portal:noah:getPaymentMethodsResult',
|
|
611
|
+
data: {},
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
}
|
|
521
615
|
getSwapsQuoteV2(data, options) {
|
|
522
616
|
return __awaiter(this, void 0, void 0, function* () {
|
|
523
617
|
return this.handleRequestToIframeAndPost({
|
|
@@ -29,5 +29,6 @@ __exportStar(require("./api"), exports);
|
|
|
29
29
|
__exportStar(require("./yieldxyz"), exports);
|
|
30
30
|
__exportStar(require("./zero-x"), exports);
|
|
31
31
|
__exportStar(require("./lifi"), exports);
|
|
32
|
+
__exportStar(require("./noah"), exports);
|
|
32
33
|
__exportStar(require("./hypernative"), exports);
|
|
33
34
|
__exportStar(require("./blockaid"), exports);
|
package/lib/esm/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import Mpc from './mpc';
|
|
|
12
12
|
import Provider, { RequestMethod } from './provider';
|
|
13
13
|
import Yield from './integrations/yield';
|
|
14
14
|
import Trading from './integrations/trading';
|
|
15
|
+
import Ramps from './integrations/ramps';
|
|
15
16
|
import Security from './integrations/security';
|
|
16
17
|
import Delegations from './integrations/delegations';
|
|
17
18
|
import PasskeyService from './passkeys';
|
|
@@ -66,6 +67,7 @@ class Portal {
|
|
|
66
67
|
portal: this,
|
|
67
68
|
});
|
|
68
69
|
this.yield = new Yield({ mpc: this.mpc });
|
|
70
|
+
this.ramps = new Ramps({ mpc: this.mpc });
|
|
69
71
|
this.trading = new Trading({ mpc: this.mpc });
|
|
70
72
|
this.security = new Security({ mpc: this.mpc });
|
|
71
73
|
this.delegations = new Delegations({ mpc: this.mpc });
|
|
@@ -668,6 +670,10 @@ class Portal {
|
|
|
668
670
|
return response;
|
|
669
671
|
});
|
|
670
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Build, sign, and broadcast a native SOL transfer on the given Solana CAIP-2 `chainId`.
|
|
675
|
+
* `to` must be a valid Solana public key (base58); `lamports` must be a positive integer.
|
|
676
|
+
*/
|
|
671
677
|
sendSol({ chainId, to, lamports, }) {
|
|
672
678
|
var _a;
|
|
673
679
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -675,9 +681,16 @@ class Portal {
|
|
|
675
681
|
if (!chainId.startsWith('solana:')) {
|
|
676
682
|
throw new Error('[Portal] Invalid chainId. Please provide a chainId that starts with "solana:"');
|
|
677
683
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
684
|
+
if (!to || typeof to !== 'string') {
|
|
685
|
+
throw new Error('[Portal] Invalid "to" Solana address provided');
|
|
686
|
+
}
|
|
687
|
+
const toTrimmed = to.trim();
|
|
688
|
+
let toPublicKey;
|
|
689
|
+
try {
|
|
690
|
+
toPublicKey = new PublicKey(toTrimmed);
|
|
691
|
+
}
|
|
692
|
+
catch (_b) {
|
|
693
|
+
throw new Error('[Portal] Invalid "to" Solana address provided (not a valid public key)');
|
|
681
694
|
}
|
|
682
695
|
// Validate the lamports.
|
|
683
696
|
if (typeof lamports !== 'number' || lamports <= 0) {
|
|
@@ -708,8 +721,6 @@ class Portal {
|
|
|
708
721
|
new Connection(gatewayUrl, 'confirmed');
|
|
709
722
|
// The sender's public key.
|
|
710
723
|
const fromPublicKey = new PublicKey(solanaAddress);
|
|
711
|
-
// The recipient's public key.
|
|
712
|
-
const toPublicKey = new PublicKey(to);
|
|
713
724
|
// Create a new transaction.
|
|
714
725
|
const transaction = new SolanaTransaction().add(SystemProgram.transfer({
|
|
715
726
|
fromPubkey: fromPublicKey,
|
package/lib/esm/index.test.js
CHANGED
|
@@ -514,7 +514,7 @@ describe('Portal', () => {
|
|
|
514
514
|
chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
515
515
|
to: 'test',
|
|
516
516
|
lamports: 10000,
|
|
517
|
-
})).rejects.toThrow(new Error('[Portal] Invalid "to" Solana address provided
|
|
517
|
+
})).rejects.toThrow(new Error('[Portal] Invalid "to" Solana address provided (not a valid public key)'));
|
|
518
518
|
}));
|
|
519
519
|
it('should throw an error if the lamports arg is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
520
520
|
yield expect(portal.sendSol({
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Noah fiat on/off-ramp API on `portal.ramps.noah`.
|
|
12
|
+
* Each method forwards to the embedded Portal iframe, which calls connect-api.
|
|
13
|
+
*/
|
|
14
|
+
export default class Noah {
|
|
15
|
+
constructor({ mpc }) {
|
|
16
|
+
this.mpc = mpc;
|
|
17
|
+
}
|
|
18
|
+
/** Start hosted KYC; response includes `hostedUrl` to open in a browser tab. */
|
|
19
|
+
initiateKyc(data) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
return this.mpc.initiateKyc(data);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** Create a pay-in (fiat → crypto) with bank transfer instructions. */
|
|
25
|
+
initiatePayin(data) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
return this.mpc.initiatePayin(data);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** Dry-run pay-in pricing / eligibility for a payment method and fiat amount. */
|
|
31
|
+
simulatePayin(data) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
return this.mpc.simulatePayin(data);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Countries supported for fiat payouts. */
|
|
37
|
+
getPayoutCountries() {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
return this.mpc.getPayoutCountries();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** Available payout rails for a country / currency pair. */
|
|
43
|
+
getPayoutChannels(data) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
return this.mpc.getPayoutChannels(data);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Dynamic form schema for a payout channel (recipient fields). */
|
|
49
|
+
getPayoutChannelForm(channelId) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
return this.mpc.getPayoutChannelForm(channelId);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** Quote fees and crypto amount for a payout channel and form payload. */
|
|
55
|
+
getPayoutQuote(data) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
return this.mpc.getPayoutQuote(data);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/** Start payout execution; may return on-chain deposit `conditions` for crypto legs. */
|
|
61
|
+
initiatePayout(data) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
return this.mpc.initiatePayout(data);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/** Pay-in payment methods available to the customer. */
|
|
67
|
+
getPaymentMethods() {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
return this.mpc.getPaymentMethods();
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|