Polywallet - An authentication layer for Bitcoin (SV) apps using Bitcoin SV wallets
No wallets are built the same—Polywallet resolves the ambiguities faced by developers using Bitcoin SV wallets.
Polywallet is an abstraction that enables you to keep your applications wallet agnostic and allow your customers to select whatever wallet they desire.
Wallet Support
Wallet | Status | Interfaces Supported |
---|---|---|
HandCash | RELEASED | Wallet, Balance, Encryption, Signatures, Paymail |
Money Button | RELEASED | Wallet, Balance, Encryption, Signatures, Paymail |
RelayX | RELEASED | Wallet, Balance, Encryption, Signatures, Paymail |
Sensilet | RELEASED | Wallet, Balance, Signatures |
Twetch | RELEASED | Wallet, Signatures, Paymail |
Volt | RELEASED | Wallet, Balance |
Dot | NOT PLANNED | TBD |
Relysia | NOT PLANNED | TBD |
Install (npm)
# Core (required)
npm install @polywallet/core
# Authentication modal (optional)
npm install @polywallet/modal
# Wallets (optional)
npm install @polywallet/handcash-adapter
npm install @polywallet/money-button-adapter
npm install @polywallet/relayx-adapter
npm install @polywallet/sensilet-adapter
npm install @polywallet/twetch-adapter
npm install @polywallet/volt-adapter
Install (CDN)
<script src="https://unpkg.com/@polywallet/bundle></script>
Usage
Import (npm)
import { Polywallet, WalletBuilder } from '@polywallet/core';
import { PolywalletModal } from '@polywallet/modal';
import { HandCashWallet } from '@polywallet/handcash-adapter';
import { MoneyButtonWallet } from '@polywallet/money-button-adapter';
import { RelayXWallet } from '@polywallet/relayx-adapter';
import { SensiletWallet } from '@polywallet/sensilet-adapter';
import { TwetchWallet } from '@polywallet/twetch-adapter';
import { VoltWallet } from '@polywallet/volt-adapter';
If you are using @polywallet/modal, include its stylesheet.
-
Angular
// angular.json ... "styles": [ ..., "node_modules/@polywallet/modal/lib/styles.css" ], ...
-
React
// Next.js: pages/_app.tsx // React: src/App.tsx ... import '@polywallet/modal/lib/styles.css'; ...
Import (CDN)
All exported members will be exposed under the global variable Polywallet
.
If you are using @polywallet/modal, its stylesheet will load automatically.
Wallet Builders
// Wallet Type Aliases:
// - SignableWallet = Wallet + Balance + Signatures
// - PaymailWallet = SignableWallet + Paymail
// - PaymailWalletWithoutBalance = PaymailWallet - Balance
// - EncryptableWallet = PaymailWallet + Encryption
import { Polywallet, WalletBuilder } from '@polywallet/core';
import { PolywalletModal } from '@polywallet/modal';
import { HandCashWallet } from '@polywallet/handcash-adapter';
import { MoneyButtonWallet } from '@polywallet/money-button-adapter';
import { RelayXWallet } from '@polywallet/relayx-adapter';
import { SensiletWallet } from '@polywallet/sensilet-adapter';
import { TwetchWallet } from '@polywallet/twetch-adapter';
import { VoltWallet } from '@polywallet/volt-adapter';
const wallet = await new WalletBuilder<Polywallet.Wallet>()
.with(HandCashWallet, { appId: 'APP_ID', appSecret: 'APP_SECRET' })
.with(MoneyButtonWallet, { clientIdentifier: 'CLIENT_IDENTIFIER' })
.with(RelayXWallet, { bitcomPrefix: 'BITCOM_PREFIX' })
.with(SensiletWallet)
.with(TwetchWallet)
.with(VoltWallet)
.withModal(PolywalletModal, {
mode: 'COMPACT',
theme: 'LIGHT',
})
.build();
const signableWallet = await new WalletBuilder<Polywallet.SignableWallet>()
.with(HandCashWallet, { appId: 'APP_ID', appSecret: 'APP_SECRET' })
.with(MoneyButtonWallet, { clientIdentifier: 'CLIENT_IDENTIFIER' })
.with(RelayXWallet, { bitcomPrefix: 'BITCOM_PREFIX' })
.with(SensiletWallet)
.withModal(PolywalletModal, {
mode: 'STANDARD',
theme: 'DARK',
afterClosed: () => console.log('Modal is closed!'),
})
.build();
const paymailWallet =
await new WalletBuilder<Polywallet.PaymailWallet>()
.with(HandCashWallet, { appId: 'APP_ID', appSecret: 'APP_SECRET' })
.with(MoneyButtonWallet, { clientIdentifier: 'CLIENT_IDENTIFIER' })
.with(RelayXWallet, { bitcomPrefix: 'BITCOM_PREFIX' })
.withHandler((wallets) => {
console.log('Authenticate manually!');
wallets[0].authenticate();
})
.build();
const paymailWalletWithoutBalance =
await new WalletBuilder<Polywallet.PaymailWalletWithoutBalance>()
.with(HandCashWallet, { appId: 'APP_ID', appSecret: 'APP_SECRET' })
.with(MoneyButtonWallet, { clientIdentifier: 'CLIENT_IDENTIFIER' })
.with(RelayXWallet, { bitcomPrefix: 'BITCOM_PREFIX' })
.with(TwetchWallet)
.withHandler((wallets) => {
console.log('Authenticate manually!');
wallets[0].authenticate();
})
.build();
const encryptablePaymailWallet =
await new WalletBuilder<Polywallet.EncryptablePaymailWallet>()
.with(HandCashWallet, { appId: 'APP_ID', appSecret: 'APP_SECRET' })
.with(MoneyButtonWallet, { clientIdentifier: 'CLIENT_IDENTIFIER' })
.with(RelayXWallet, { bitcomPrefix: 'BITCOM_PREFIX' })
.withModal(PolywalletModal)
.build();
// Once we have the EncryptablePaymailWallet, we can do all these things
// regardless of which wallet the customer chose.
const meta = [109, 101, 116, 97];
await encryptablePaymailWallet.sign(meta);
await encryptablePaymailWallet.decrypt(await wallet.encrypt(meta));
await encryptablePaymailWallet.sendToBitcoinAddress(
'11A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
1,
);
Modal
The polywallet modal can also be opened and closed manually.
import { PolywalletModal } from '@polywallet/modal';
const wallet = new AnyWallet();
const modal = new PolywalletModal({
mode: 'STANDARD',
theme: 'DARK',
afterClosed: () => console.log('Modal is closed!'),
});
modal.open([wallet]);
modal.close();
Support
Reach out to us at info@monetize.li to request support or other inquiries.
DM @McGooserJr for any questions—and to stay updated with upcoming releases!