-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* generate offramp url * initOffRamp * fix vulnerability * change param name * change path to sell * add sessionToken * add test * lint * fix vulnerability * revert * make aggregator params optional for now * fix comment
- Loading branch information
Showing
10 changed files
with
467 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { generateOffRampURL } from './generateOffRampURL'; | ||
|
||
describe('generateOffRampURL', () => { | ||
it('generates URL with expected default parameters', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
appId: 'test', | ||
}), | ||
); | ||
|
||
expect(url.origin).toEqual('https://pay.coinbase.com'); | ||
expect(url.pathname).toEqual('/v3/sell/input'); | ||
expect(url.searchParams.get('appId')).toEqual('test'); | ||
}); | ||
|
||
it('should support redirectUrl', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
appId: 'test', | ||
redirectUrl: 'https://example.com', | ||
}), | ||
); | ||
|
||
expect(url.searchParams.get('redirectUrl')).toEqual('https://example.com'); | ||
}); | ||
|
||
it('generates URL with multiple addresses', () => { | ||
const addresses = { | ||
'0x1': ['base', 'ethereum'], | ||
'123abc': ['solana'], | ||
}; | ||
|
||
const url = new URL( | ||
generateOffRampURL({ | ||
appId: 'test', | ||
addresses, | ||
redirectUrl: 'https://example.com', | ||
}), | ||
); | ||
|
||
expect(url.searchParams.get('addresses')).toEqual( | ||
'{"0x1":["base","ethereum"],"123abc":["solana"]}', | ||
); | ||
}); | ||
|
||
it('generates URL with multiple addresses and assets', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
appId: 'test', | ||
addresses: { | ||
'0x5ome4ddre55': ['ethereum', 'avalanche-c-chain'], | ||
'90123jd09ef09df': ['solana'], | ||
}, | ||
assets: ['USDC', 'SOL'], | ||
}), | ||
); | ||
|
||
expect(url.searchParams.get('addresses')).toEqual( | ||
`{\"0x5ome4ddre55\":[\"ethereum\",\"avalanche-c-chain\"],\"90123jd09ef09df\":[\"solana\"]}`, | ||
); | ||
expect(url.searchParams.get('assets')).toEqual('["USDC","SOL"]'); | ||
}); | ||
|
||
it('should support dynamic host', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
host: 'http://localhost:3000', | ||
appId: 'test', | ||
}), | ||
); | ||
|
||
expect(url.origin).toEqual('http://localhost:3000'); | ||
expect(url.pathname).toEqual('/v3/sell/input'); | ||
expect(url.searchParams.get('appId')).toEqual('test'); | ||
}); | ||
|
||
it('should support preset amounts', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
appId: 'test', | ||
presetCryptoAmount: 0.1, | ||
presetFiatAmount: 20, | ||
}), | ||
); | ||
|
||
expect(url.searchParams.get('presetFiatAmount')).toEqual('20'); | ||
expect(url.searchParams.get('presetCryptoAmount')).toEqual('0.1'); | ||
}); | ||
|
||
it('should support defaultNetwork', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
appId: 'test', | ||
defaultNetwork: 'ethereum', | ||
}), | ||
); | ||
expect(url.searchParams.get('defaultNetwork')).toEqual('ethereum'); | ||
}); | ||
|
||
it('should support sessionToken', () => { | ||
const url = new URL( | ||
generateOffRampURL({ | ||
sessionToken: 'test', | ||
}), | ||
); | ||
expect(url.origin).toEqual('https://pay.coinbase.com'); | ||
expect(url.pathname).toEqual('/v3/sell/input'); | ||
expect(url.searchParams.get('sessionToken')).toEqual('test'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { OffRampAppParams } from 'types/offramp'; | ||
import { DEFAULT_HOST } from '../config'; | ||
import type { Theme } from '../types/widget'; | ||
|
||
export type GenerateOffRampURLOptions = { | ||
/** This & addresses or sessionToken are required. */ | ||
appId?: string; | ||
host?: string; | ||
theme?: Theme; | ||
/** This or appId & addresses are required. */ | ||
sessionToken?: string; | ||
} & OffRampAppParams; | ||
|
||
export const generateOffRampURL = ({ | ||
host = DEFAULT_HOST, | ||
...props | ||
}: GenerateOffRampURLOptions): string => { | ||
const url = new URL(host); | ||
url.pathname = '/v3/sell/input'; | ||
|
||
(Object.keys(props) as (keyof typeof props)[]).forEach((key) => { | ||
const value = props[key]; | ||
if (value !== undefined) { | ||
if (['string', 'number', 'boolean'].includes(typeof value)) { | ||
url.searchParams.append(key, value.toString()); | ||
} else { | ||
url.searchParams.append(key, JSON.stringify(value)); | ||
} | ||
} | ||
}); | ||
|
||
url.searchParams.sort(); | ||
|
||
return url.toString(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { initOffRamp } from './initOffRamp'; | ||
import { CBPayInstance } from '../utils/CBPayInstance'; | ||
|
||
jest.mock('../utils/CBPayInstance'); | ||
|
||
describe('initOffRamp', () => { | ||
it('should return CBPayInstance', async () => { | ||
let instance: unknown; | ||
initOffRamp( | ||
{ | ||
experienceLoggedIn: 'popup', | ||
experienceLoggedOut: 'popup', | ||
appId: 'abc123', | ||
widgetParameters: { addresses: { '0x1': ['base'] }, redirectUrl: 'https://example.com' }, | ||
}, | ||
(_, newInstance) => { | ||
instance = newInstance; | ||
}, | ||
); | ||
|
||
expect(CBPayInstance).toHaveBeenCalledTimes(1); | ||
|
||
expect(instance instanceof CBPayInstance).toBe(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { CBPayExperienceOptions } from '../types/widget'; | ||
import { CBPayInstance, CBPayInstanceType } from '../utils/CBPayInstance'; | ||
import { OffRampAppParams } from '../types/offramp'; | ||
|
||
export type InitOffRampParams = CBPayExperienceOptions<OffRampAppParams>; | ||
|
||
export type InitOffRampCallback = { | ||
(error: Error, instance: null): void; | ||
(error: null, instance: CBPayInstanceType): void; | ||
}; | ||
|
||
export const initOffRamp = ( | ||
{ | ||
experienceLoggedIn = 'new_tab', // default experience type | ||
widgetParameters, | ||
...options | ||
}: InitOffRampParams, | ||
callback: InitOffRampCallback, | ||
): void => { | ||
const instance = new CBPayInstance({ | ||
...options, | ||
widget: 'sell', | ||
experienceLoggedIn, | ||
appParams: widgetParameters, | ||
}); | ||
callback(null, instance); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
export type BaseOffRampAppParams = { | ||
/** | ||
* | ||
* Each entry in the record represents a wallet address and the networks it is valid for. There should only be a | ||
* single address for each network your app supports. Users will be able to cash out any owned assets supported by any of | ||
* the networks you specify. See the assets parameter if you want to restrict the available assets. | ||
* | ||
* Example: | ||
* | ||
* Show all assets users have on the base network, only on the base network: | ||
* | ||
* `{ "0x1": ["base"] }` | ||
* | ||
*/ | ||
addresses?: Record<string, string[]>; | ||
/** A URL that the user will be redirected to after to sign their transaction after the transaction has been committed. */ | ||
redirectUrl?: string; | ||
/** | ||
* This optional parameter will restrict the assets available for the user to cash out. It acts as a filter on the | ||
* networks specified in the {addresses} param. | ||
* | ||
* Example: | ||
* | ||
* Support only USDC on either the base network or the ethereum network: | ||
* | ||
* `addresses: { "0x1": ["base", "ethereum"] }, assets: ["USDC"]` | ||
* | ||
*/ | ||
assets?: string[]; | ||
/** The default network that should be selected when multiple networks are present. */ | ||
defaultNetwork?: string; | ||
/** The preset input amount as a crypto value. i.e. 0.1 ETH. */ | ||
presetCryptoAmount?: number; | ||
/** | ||
* The preset input amount as a fiat value. i.e. 15 USD. | ||
* Ignored if presetCryptoAmount is also set. | ||
* Also note this only works for a subset of fiat currencies: USD, CAD, GBP, EUR | ||
* */ | ||
presetFiatAmount?: number; | ||
/** ID used to link all user transactions created during the session. */ | ||
partnerUserId?: string; | ||
}; | ||
|
||
export type OffRampAggregatorAppParams = { | ||
quoteId?: string; | ||
defaultAsset?: string; | ||
defaultNetwork?: string; | ||
defaultCashoutMethod?: string; // "CRYPTO_ACCOUNT" | "FIAT_WALLET" | "CARD" | "ACH_BANK_ACCOUNT" | "PAYPAL" | ||
presetFiatAmount?: number; | ||
fiatCurrency?: string; | ||
}; | ||
|
||
export type OffRampAppParams = | ||
| BaseOffRampAppParams | ||
| (BaseOffRampAppParams & OffRampAggregatorAppParams); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.