@ledgerhq/coin-algorand
Version:
Ledger Algorand Coin integration
70 lines (53 loc) • 1.94 kB
text/typescript
import { Observable } from "rxjs";
import { FeeNotLoaded } from "@ledgerhq/errors";
import type { AccountBridge } from "@ledgerhq/types-live";
import { SignerContext } from "@ledgerhq/coin-framework/signer";
import { buildTransactionPayload, encodeToBroadcast, encodeToSign } from "./buildTransaction";
import { buildOptimisticOperation } from "./buildOptimisticOperation";
import type { AlgorandAccount, AlgorandTransaction } from "./types";
import type { AlgorandSigner } from "./signer";
/**
* Sign Transaction with Ledger hardware
*/
export const buildSignOperation =
(
signerContext: SignerContext<AlgorandSigner>,
): AccountBridge<AlgorandTransaction, AlgorandAccount>["signOperation"] =>
({ account, transaction, deviceId }) =>
new Observable(o => {
let cancelled = false;
async function main() {
if (!transaction.fees) {
throw new FeeNotLoaded();
}
const algoTx = await buildTransactionPayload(account, transaction);
const toSign = encodeToSign(algoTx);
const { freshAddressPath } = account;
o.next({ type: "device-signature-requested" });
const { signature } = await signerContext(deviceId, signer =>
signer.sign(freshAddressPath, toSign),
);
if (cancelled) return;
o.next({ type: "device-signature-granted" });
if (!signature) {
throw new Error("No signature");
}
const toBroadcast = encodeToBroadcast(algoTx, signature);
const operation = buildOptimisticOperation(account, transaction);
o.next({
type: "signed",
signedOperation: {
operation,
signature: toBroadcast.toString("hex"),
},
});
}
main().then(
() => o.complete(),
e => o.error(e),
);
return () => {
cancelled = true;
};
});
export default buildSignOperation;