@bsv/wallet-toolbox-client
Version:
Client only Wallet Storage
113 lines • 5.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletAuthenticationManager = void 0;
const CWIStyleWalletManager_1 = require("./CWIStyleWalletManager");
const sdk_1 = require("@bsv/sdk");
/**
* WalletAuthenticationManager
*
* A wallet manager that integrates
* with a WABClient for user authentication flows (e.g. Twilio phone).
*/
class WalletAuthenticationManager extends CWIStyleWalletManager_1.CWIStyleWalletManager {
constructor(adminOriginator, walletBuilder, interactor = new CWIStyleWalletManager_1.OverlayUMPTokenInteractor(), recoveryKeySaver, passwordRetriever, wabClient, authMethod, stateSnapshot) {
super(adminOriginator, walletBuilder, interactor, recoveryKeySaver, passwordRetriever,
// Here, we provide a custom new wallet funder that uses the Secret Server
async (presentationKey, wallet, adminOriginator) => {
debugger;
const { paymentData } = await this.wabClient.requestFaucet(sdk_1.Utils.toHex(presentationKey));
if (!paymentData.k || !paymentData.tx) {
throw new Error('Invalid');
}
const tx = sdk_1.Transaction.fromAtomicBEEF(paymentData.tx);
console.log(paymentData);
const faucetRedeemTXCreationResult = await wallet.createAction({
inputBEEF: tx.toBEEF(),
inputs: [
{
outpoint: `${paymentData.txid}.0`,
unlockingScriptLength: 108,
inputDescription: 'Fund from faucet'
}
],
description: 'Fund wallet',
options: {
acceptDelayedBroadcast: false
}
}, adminOriginator);
const faucetRedeemTX = sdk_1.Transaction.fromAtomicBEEF(faucetRedeemTXCreationResult.signableTransaction.tx);
const faucetRedemptionPuzzle = new sdk_1.RPuzzle();
const randomRedemptionPrivateKey = sdk_1.PrivateKey.fromRandom();
const faucetRedeemUnlocker = faucetRedemptionPuzzle.unlock(new sdk_1.BigNumber(paymentData.k, 16), randomRedemptionPrivateKey);
const faucetRedeemUnlockingScript = await faucetRedeemUnlocker.sign(faucetRedeemTX, 0);
const signActionResult = await wallet.signAction({
reference: faucetRedeemTXCreationResult.signableTransaction.reference,
spends: {
0: {
unlockingScript: faucetRedeemUnlockingScript.toHex()
}
}
});
console.log('Sign action result:', signActionResult);
}, stateSnapshot);
this.wabClient = wabClient;
this.authMethod = authMethod;
}
/**
* Sets (or switches) the chosen AuthMethodInteractor at runtime,
* in case the user changes their mind or picks a new method in the UI.
*/
setAuthMethod(method) {
this.authMethod = method;
}
/**
* Initiate the WAB-based flow, e.g. sending an SMS code or starting an ID check,
* using the chosen AuthMethodInteractor.
*/
async startAuth(payload) {
if (!this.authMethod) {
throw new Error('No AuthMethod selected in WalletAuthenticationManager');
}
this.tempPresentationKey = this.generateTemporaryPresentationKey();
// For example, if this.authMethod is Twilio, `payload` might contain { phoneNumber: "+1..." }
const startRes = await this.wabClient.startAuthMethod(this.authMethod,
// The user might not have a presentationKey yet, so we generate one locally to pass to the server.
// If it’s an existing user on the WAB side, the WAB will give us the stored key later.
// But we do need some placeholder key for the 'startAuth' call:
this.tempPresentationKey, payload);
if (!startRes.success) {
throw new Error(startRes.message || 'Failed to start WAB auth method');
}
}
/**
* Completes the WAB-based flow, retrieving the final presentationKey from WAB if successful.
*/
async completeAuth(payload) {
if (!this.authMethod || !this.tempPresentationKey) {
throw new Error('No AuthMethod selected in WalletAuthenticationManager or startAuth has yet to be called.');
}
// Unser the temp presentation key early (for security)
const tempKey = this.tempPresentationKey;
this.tempPresentationKey = undefined;
const result = await this.wabClient.completeAuthMethod(this.authMethod, tempKey, payload);
if (!result.success || !result.presentationKey) {
throw new Error(result.message || 'Failed to complete WAB auth');
}
// We now have the final 256-bit key in hex from the WAB
const presentationKeyHex = result.presentationKey;
const presentationKeyBytes = sdk_1.Utils.toArray(presentationKeyHex, 'hex');
// Provide this presentation key to the underlying CWI logic:
// This sets 'this.presentationKey' and determines if it's a new or existing user
// based on whether a UMP token exists on chain. We'll do "presentation-key-and-password"
// for new user flows, for example, or user might choose "presentation-key-and-recovery-key" if we wanted.
// Either way, WAB has now done its job and we are off to base-layer CWI logic at this point!
await this.providePresentationKey(presentationKeyBytes);
}
generateTemporaryPresentationKey() {
// For the 'startAuth' call, we can generate a random 32 bytes → 64 hex chars.
const randomBytes = (0, sdk_1.Random)(32); // array of length 32
return sdk_1.Utils.toHex(randomBytes);
}
}
exports.WalletAuthenticationManager = WalletAuthenticationManager;
//# sourceMappingURL=WalletAuthenticationManager.js.map