-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Tyler Whitman <[email protected]>
- Loading branch information
1 parent
37ac9ef
commit bf4e89a
Showing
13 changed files
with
718 additions
and
12 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# `@helium/wallet-link` | ||
|
||
Utilities for linking a 3rd party app to the helium wallet. The link token is used for hotspot onboarding, location | ||
assertion, and ownership transfer transaction signing with the Helium Wallet and Hotspot apps. | ||
|
||
## Installation | ||
|
||
### React Native | ||
|
||
```shell | ||
$ yarn add @helium/wallet-link @helium/crypto-react-native | ||
$ yarn add --dev patch-package postinstall-postinstall | ||
# or | ||
$ npm install @helium/wallet-link @helium/crypto-react-native | ||
$ npm install --save-dev patch-package | ||
``` | ||
|
||
When using this library in React Native you must patch the `@helium/crypto` calls | ||
with `@helium/crypto-react-native`. You can do this using [patch-package](https://github.com/ds300/patch-package) | ||
by adding the following file to your React Native root at `/patches/@wallet-link+4.4.0.patch`. | ||
|
||
``` | ||
TODO: Add patch | ||
``` | ||
|
||
### Browser or other JS environments | ||
|
||
```shell | ||
$ yarn add @helium/wallet-link @helium/crypto | ||
# or | ||
$ npm install @helium/wallet-link @helium/crypto | ||
``` | ||
|
||
## Usage | ||
|
||
```ts | ||
// Create link to Helium app | ||
const url = createWalletLinkUrl({ | ||
universalLink: 'https://wallet.helium.com/', | ||
requestAppId: 'com.maker.app', | ||
callbackUrl: 'makerappscheme://', | ||
appName: 'Maker App', | ||
}) | ||
|
||
Linking.openURL(url) | ||
|
||
// parse received token | ||
const parsed = parseWalletLinkToken(token) | ||
|
||
// verify token | ||
const verified = verifyWalletLinkToken(parsed) | ||
|
||
// verify token with max age | ||
const verified = verifyWalletLinkToken(parsed, { maxAgeInSeconds: 60 }) | ||
|
||
// Create link to update a hotspot | ||
const updateParams = { | ||
token, | ||
platform: Platform.OS, | ||
addGatewayTxn: 'your_optional_unsigned_txn', | ||
assertLocationTxn: 'your_optional_unsigned_txn', | ||
transferHotspotTxn: 'your_optional_unsigned_txn', | ||
} as SignHotspotRequest | ||
|
||
const url = createUpdateHotspotUrl(updateParams) | ||
Linking.openURL(url) | ||
|
||
// submit signed txn | ||
``` |
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,40 @@ | ||
{ | ||
"name": "@helium/wallet-link", | ||
"version": "4.4.0", | ||
"description": "Utilities for linking a 3rd party app to the helium wallet.", | ||
"keywords": [ | ||
"helium", | ||
"blockchain", | ||
"react-native" | ||
], | ||
"contributors": [ | ||
"Matt Reetz <[email protected]>" | ||
], | ||
"homepage": "https://github.com/helium/helium-js#readme", | ||
"license": "Apache-2.0", | ||
"main": "build/index.js", | ||
"module": "build/index.es.js", | ||
"files": [ | ||
"build" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: run tests from root\" && exit 1", | ||
"clean": "rimraf build", | ||
"build": "yarn run clean && tsc" | ||
}, | ||
"dependencies": { | ||
"@helium/address": "^4.3.1", | ||
"@helium/transactions": "^4.3.1", | ||
"date-fns": "^2.28.0", | ||
"query-string": "^7.1.1" | ||
}, | ||
"peerDependencies": { | ||
"@helium/crypto": "^4.3.1" | ||
}, | ||
"devDependencies": { | ||
"@helium/crypto": "^4.3.1" | ||
} | ||
} |
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,156 @@ | ||
import { Keypair } from '@helium/crypto' | ||
import { getUnixTime } from 'date-fns' | ||
import { | ||
createLinkWalletCallbackUrl, | ||
createSignHotspotCallbackUrl, | ||
createUpdateHotspotUrl, | ||
createWalletLinkUrl, | ||
LinkWalletResponse, | ||
makeAppLinkAuthToken, | ||
parseWalletLinkToken, | ||
SignHotspotRequest, | ||
SignHotspotResponse, | ||
verifyWalletLinkToken, | ||
} from '../index' | ||
|
||
const createToken = async ({ | ||
time, | ||
signingAppId, | ||
} : { time?: number, signingAppId?: string } = {}) => { | ||
const keypair = await Keypair.makeRandom() | ||
const opts = { | ||
address: keypair.address.b58, | ||
appName: 'tacos', | ||
callbackUrl: 'myscheme://', | ||
requestAppId: 'com.tacos', | ||
signingAppId: signingAppId || 'com.burrito', | ||
time: time || new Date().getTime(), | ||
} | ||
const token = await makeAppLinkAuthToken(opts, keypair) | ||
return { token: parseWalletLinkToken(token), opts, tokenString: token } | ||
} | ||
|
||
describe('wallet-link', () => { | ||
describe('create link', () => { | ||
it('successfully creates and parses', async () => { | ||
const { token, opts } = await createToken() | ||
expect(token.address).toBe(opts.address) | ||
expect(token.signature).toBeDefined() | ||
expect(token.appName).toBe(opts.appName) | ||
expect(token.callbackUrl).toBe(opts.callbackUrl) | ||
expect(token.requestAppId).toBe(opts.requestAppId) | ||
expect(token.signingAppId).toBe(opts.signingAppId) | ||
expect(token.time).toBe(opts.time) | ||
}) | ||
}) | ||
|
||
describe('verify link', () => { | ||
it('validates token without opts', async () => { | ||
const { token } = await createToken() | ||
const verified = await verifyWalletLinkToken(token) | ||
expect(verified).toBe(true) | ||
}) | ||
|
||
it('validates token with max age', async () => { | ||
const { token } = await createToken() | ||
const verified = await verifyWalletLinkToken(token, { maxAgeInSeconds: 60 }) | ||
expect(verified).toBe(true) | ||
}) | ||
|
||
it('invalidates expired token', async () => { | ||
const { token } = await createToken({ time: getUnixTime(new Date()) - 60 }) | ||
expect(() => verifyWalletLinkToken(token, { maxAgeInSeconds: 30 })).toThrow('Token is expired') | ||
}) | ||
}) | ||
|
||
describe('create urls', () => { | ||
it('creates wallet link url', async () => { | ||
const params = { | ||
requestAppId: 'testRequestAppId', | ||
callbackUrl: 'testCallbackUrl', | ||
appName: 'testAppName', | ||
universalLink: 'testUniversalLink', | ||
path: 'testPath', | ||
} | ||
const callbackUrl = createWalletLinkUrl(params) | ||
expect(callbackUrl).toBe('testUniversalLinktestPath?appName=testAppName&callbackUrl=testCallbackUrl' | ||
+ '&requestAppId=testRequestAppId') | ||
}) | ||
|
||
it('creates callback url', async () => { | ||
const params: LinkWalletResponse = { | ||
status: 'success', | ||
token: 'testToken', | ||
} | ||
const callbackUrl = createLinkWalletCallbackUrl('test://', 'testAddress', params) | ||
expect(callbackUrl).toBe('test://link_wallet/testAddress?status=success&token=testToken') | ||
}) | ||
|
||
it('creates sign hotspot callback url', async () => { | ||
const params: SignHotspotResponse = { | ||
status: 'success', | ||
assertTxn: 'testAssertTxn', | ||
gatewayTxn: 'testGatewayTxn', | ||
transferTxn: 'testTransferTxn', | ||
gatewayAddress: 'testGatewayAddress', | ||
} | ||
const callbackUrl = createSignHotspotCallbackUrl('test://', params) | ||
expect(callbackUrl).toBe('test://sign_hotspot?assertTxn=testAssertTxn&gatewayAddress=testGatewayAddress' | ||
+ '&gatewayTxn=testGatewayTxn&status=success&transferTxn=testTransferTxn') | ||
}) | ||
|
||
it('creates ios update hotspot url', async () => { | ||
const { tokenString } = await createToken({ signingAppId: 'com.helium.wallet.app' }) | ||
const params: SignHotspotRequest = { | ||
token: tokenString, | ||
addGatewayTxn: 'testAddGatewayTxn', | ||
assertLocationTxn: 'testAssertLocationTxn', | ||
transferHotspotTxn: 'testTransferHotspotTxn', | ||
platform: 'ios', | ||
} | ||
const callbackUrl = createUpdateHotspotUrl(params) | ||
expect(callbackUrl).toBe('https://wallet.helium.com/sign_hotspot?addGatewayTxn=testAddGatewayTxn' | ||
+ `&assertLocationTxn=testAssertLocationTxn&platform=ios&token=${encodeURIComponent(tokenString)}` | ||
+ '&transferHotspotTxn=testTransferHotspotTxn') | ||
}) | ||
|
||
it('creates android update hotspot url', async () => { | ||
const { tokenString } = await createToken({ signingAppId: 'com.helium.wallet.app' }) | ||
const params: SignHotspotRequest = { | ||
token: tokenString, | ||
addGatewayTxn: 'testAddGatewayTxn', | ||
assertLocationTxn: 'testAssertLocationTxn', | ||
transferHotspotTxn: 'testTransferHotspotTxn', | ||
platform: 'android', | ||
} | ||
const callbackUrl = createUpdateHotspotUrl(params) | ||
expect(callbackUrl).toBe('https://wallet.helium.com/sign_hotspot?addGatewayTxn=testAddGatewayTxn' | ||
+ `&assertLocationTxn=testAssertLocationTxn&platform=android&token=${encodeURIComponent(tokenString)}` | ||
+ '&transferHotspotTxn=testTransferHotspotTxn') | ||
}) | ||
|
||
it('fails for invalid platform', async () => { | ||
const { tokenString } = await createToken({ signingAppId: 'com.helium.wallet.app' }) | ||
const params: SignHotspotRequest = { | ||
token: tokenString, | ||
addGatewayTxn: 'testAddGatewayTxn', | ||
assertLocationTxn: 'testAssertLocationTxn', | ||
transferHotspotTxn: 'testTransferHotspotTxn', | ||
platform: 'test', | ||
} | ||
expect(() => createUpdateHotspotUrl(params)).toThrow("Platform 'test' is not supported") | ||
}) | ||
|
||
it('fails for invalid signing app id', async () => { | ||
const { tokenString } = await createToken() | ||
const params: SignHotspotRequest = { | ||
token: tokenString, | ||
addGatewayTxn: 'testAddGatewayTxn', | ||
assertLocationTxn: 'testAssertLocationTxn', | ||
transferHotspotTxn: 'testTransferHotspotTxn', | ||
platform: 'android', | ||
} | ||
expect(() => createUpdateHotspotUrl(params)).toThrow('Could not find delegate app') | ||
}) | ||
}) | ||
}) |
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,8 @@ | ||
/** | ||
* [[include:wallet-link/README.md]] | ||
* @packageDocumentation | ||
* @module wallet-link | ||
*/ | ||
|
||
export * from './walletLink' | ||
export * from './types' |
Oops, something went wrong.