Skip to content

Commit

Permalink
Merge pull request #16 from Dartroom/15-extended-transaction-format
Browse files Browse the repository at this point in the history
Input and output transaction fromat extended to support @dartroom/con…
  • Loading branch information
stefdegroot committed Mar 14, 2023
2 parents 5b38953 + aab3d3b commit cea557e
Show file tree
Hide file tree
Showing 9 changed files with 517 additions and 92 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dartroom/dart-signer",
"version": "0.3.0-alpha",
"name": "@dartroom/signer",
"version": "0.3.1-alpha",
"description": "A package that aggregates multiple Algorand signing options into one interface. Handles signing and address/login management.",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
21 changes: 12 additions & 9 deletions src/algoSigner/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,27 @@ export default async function connect ({ algoSigner, ledger }: Provider) {
throw new Error('Failed to connect with the AlgoSigner. Make sure the browser extension is installed.')
}

let accounts

try {
await algoSigner.connect()
const reponse = await algoSigner.algorand.enable({
genesisID: ledger === 'TESTNET' ? 'testnet-v1.0' : 'mainnet-v1.0'
})
accounts = reponse.accounts as Array<string>
} catch (err) {
throw new Error('Failed to connect with the AlgoSigner. Make sure the browser extension is installed.')
}

let accounts

try {
accounts = await algoSigner.accounts({ ledger: ledger }) as unknown as Array<{ address: string }>
} catch (err) {
throw new Error('There were no addresses found in your AlgoSigner account. Please add an address and try again.')
}
// try {
// accounts = await algoSigner.algoSigner.accounts({ ledger: ledger }) as unknown as Array<{ address: string }>
// } catch (err) {
// throw new Error('There were no addresses found in your AlgoSigner account. Please add an address and try again.')
// }

if (accounts && accounts.length > 0) {
return accounts.map((a) => {
return {
address: a.address,
address: a,
wallet: Wallets.ALGOSIGNER
}
})
Expand Down
72 changes: 47 additions & 25 deletions src/algoSigner/signTransactions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Provider } from '../main'
import { Txn } from '../signTransactions'

export default async function sign ({ algoSigner }: Provider, txns: Array<Array<Txn>>): Promise<Array<Txn>> {
interface AlgoSignerTxn {
txn: string,
signers?: Array<string>
authAddr?: string
}

if (!algoSigner) {
export default async function sign<T extends Txn>({ algoSigner }: Provider, txns: Array<Array<T>>): Promise<Array<Array<T>>> {

if (!algoSigner?.algorand) {
throw new Error('Failed to connect with the AlgoSigner. Make sure the browser extension is installed.')
}

const binaryTxns: Array<{ txn: string, signers?: Array<string> }> = []
const unsignedTxns: Array<Txn> = []
const unsignedTxns: Array<T> = []
let formatedTxns: Array<Array<{ txn: string, signers?: Array<string> }>> = []

for (let g = 0; g < txns.length; g++) {

Expand All @@ -27,38 +33,54 @@ export default async function sign ({ algoSigner }: Provider, txns: Array<Array<
}

unsignedTxns.push(txn)

if (txn.signers.length > 1) {
binaryTxns.push({
txn: algoSigner.encoding.msgpackToBase64(txn.blob),
signers: txn.signers
})
} else {
binaryTxns.push({
txn: algoSigner.encoding.msgpackToBase64(txn.blob)
})
}
}
}

const signedTxns = await algoSigner.signTxn(binaryTxns) as unknown as Array<{ blob: string, txID: string }>
formatedTxns = txns.map((txnGroup) => {
return txnGroup.map((txn) => {
const format = {
txn: algoSigner.algorand.encoding.msgpackToBase64(txn.blob),
} as AlgoSignerTxn

if (txn.authAddress) {
format['authAddr'] = txn.authAddress
} else if (txn.signers) {
format['signers'] = txn.signers
}

return format
})
})

let formated: Array<Array<T>> = []

if (signedTxns.length > 0) {
return signedTxns.map((txn, i) => {
const signedTxns = await algoSigner.algorand.signTxns(formatedTxns) as unknown as Array<string>

const unsignedTxn = unsignedTxns[i]
if (signedTxns && signedTxns.length > 0) {
formated = txns.map((txnArray, i) => {
const unsignedArray = txns[i]
const signedArray = signedTxns.splice(0, txnArray.length)

if (!unsignedTxn) {
if (!unsignedArray) {
throw new Error('Failed to parse transaction array.')
}

return {
blob: Uint8Array.from(atob(txn.blob), c => c.charCodeAt(0)),
txID: unsignedTxn.txID,
signers: unsignedTxn.signers
}
return signedArray.map((signedTxn, index) => {
const usignedTxn = unsignedArray[index]

if (!usignedTxn) {
throw new Error('Failed to parse transaction array.')
}

return {
...usignedTxn,
blob: Uint8Array.from(algoSigner.algorand.encoding.base64ToMsgpack(signedTxn))
}
})
})
} else {
throw new Error('')
}

return formated
}
37 changes: 27 additions & 10 deletions src/exodus/signTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { Provider } from '../main'
import { Txn } from '../signTransactions'
import { decodeUnsignedTransaction } from 'algosdk'

export default async function sign ({ exodus }: Provider, txns: Array<Array<Txn>>): Promise<Array<Txn>> {
export default async function sign<T extends Txn>({ exodus }: Provider, txns: Array<Array<T>>): Promise<Array<Array<T>>> {

const binaryTxns: Array<Uint8Array> = []
const unsignedTxns: Array<Txn> = []
const unsignedTxns: Array<T> = []

for (let g = 0; g < txns.length; g++) {

Expand All @@ -28,20 +28,37 @@ export default async function sign ({ exodus }: Provider, txns: Array<Array<Txn>
}
}

let formated: Array<Array<T>> = []

const signedTxns = await exodus.signTransaction(binaryTxns) as Array<Uint8Array>

return signedTxns.map((blob, i) => {
if (signedTxns && signedTxns.length > 0) {

const unsignedTxn = unsignedTxns[i]
formated = txns.map((txnArray, i) => {
const unsignedArray = txns[i]
const signedArray = signedTxns.splice(0, txnArray.length)

if (!unsignedTxn) {
if (!unsignedArray) {
throw new Error('Failed to parse transaction array.')
}

return {
blob: blob,
signers: unsignedTxn.signers,
txID: unsignedTxn.txID
}
return signedArray.map((signedTxn, index) => {
const usignedTxn = unsignedArray[index]

if (!usignedTxn) {
throw new Error('Failed to parse transaction array.')
}

return {
...usignedTxn,
blob: signedTxn
}
})
})

} else {
throw new Error('The Exodus wallet did not return any transcactions.')
}

return formated
}
24 changes: 14 additions & 10 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import buffer from 'buffer'
import { PeraWalletConnect } from "@perawallet/connect"

import { Wrapper } from "./types/algoSigner"
import AlgoWrapper from "./types/algoSignerAlgo"

import connect, { ConnectSettings } from './connect'
import disconnect, { DisconnectSettings } from './disconnect'
import signTransaction, { type Txn } from './signTransactions'
import setActive, { ActiveSettings } from './active'

export enum Ledgers {
MAINNET = 'MainNet',
TESTNET = 'TestNet'
}
export type Ledgers = 'MAINNET' | 'TESTNET'

export enum Wallets {
MYALGO = 'MyAlgo',
Expand All @@ -39,21 +37,22 @@ export interface Pera {
export interface Provider {
myAlgo: MyAlgoConnect
pera: PeraWalletConnect
algoSigner: Wrapper | undefined
algoSigner: { algoSigner: Wrapper, algorand: AlgoWrapper } | undefined
exodus: any | undefined
ledger: Ledgers
addresses: Addresses
active: Address | undefined
}

declare var AlgoSigner: any;
declare var algorand: any;
declare var exodus: any;

export class Wallet {

myAlgo: MyAlgoConnect
pera: PeraWalletConnect;
algoSigner: Wrapper | undefined
algoSigner: { algoSigner: Wrapper, algorand: AlgoWrapper } | undefined
exodus: any | undefined
ledger: Ledgers
addresses: Addresses
Expand All @@ -62,11 +61,12 @@ export class Wallet {
constructor (options?: { ledger?: Ledgers}) {
this.myAlgo = new MyAlgoConnect()
this.pera = new PeraWalletConnect({
shouldShowSignTxnToast: false
shouldShowSignTxnToast: false,
chainId: options?.ledger ? (options.ledger === 'TESTNET' ? 416002 : 416001) : 416001
})
this.algoSigner = this.setAlgoSigner()
this.exodus = this.setExodus()
this.ledger = options?.ledger || Ledgers.MAINNET
this.ledger = options?.ledger || 'MAINNET'
this.addresses = this.getLocalAccounts()
this.active = this.getActive()
}
Expand All @@ -80,7 +80,7 @@ export class Wallet {
await disconnect(this, settings)
}

async signTransactions (txns: Array<Array<Txn>>) {
async signTransactions<T extends Txn>(txns: Array<Array<T>>): Promise<Array<Array<T>>> {
return await signTransaction(this, txns)
}

Expand Down Expand Up @@ -117,7 +117,11 @@ export class Wallet {
private setAlgoSigner () {
try {
const algoSigner = AlgoSigner
return algoSigner
const algo = algorand
return {
algoSigner: algoSigner,
algorand: algo
}
} catch {
return undefined
}
Expand Down
35 changes: 23 additions & 12 deletions src/myAlgo/signTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { Txn } from '../signTransactions'
import MyAlgoConnect, { WalletTransaction } from '@randlabs/myalgo-connect'
import { decodeUnsignedTransaction } from 'algosdk'

export default async function sign ({ }: Provider, txns: Array<Array<Txn>>): Promise<Array<Txn>> {
export default async function sign<T extends Txn>({ }: Provider, txns: Array<Array<T>>): Promise<Array<Array<T>>> {
const myAlgo = new MyAlgoConnect()

const binaryTxns: Array<Uint8Array> = []
const unsignedTxns: Array<Txn> = []
const unsignedTxns: Array<T> = []

for (let g = 0; g < txns.length; g++) {

Expand All @@ -30,24 +30,35 @@ export default async function sign ({ }: Provider, txns: Array<Array<Txn>>): Pro
}
}

const signedTxns = await myAlgo.signTransaction(binaryTxns)
let formated: Array<Array<T>> = []

if (signedTxns.length > 0) {
return signedTxns.map((txn, i) => {
const signedTxns = await myAlgo.signTransaction(binaryTxns)

const unsignedTxn = unsignedTxns[i]
if (signedTxns && signedTxns.length > 0) {
formated = txns.map((txnArray, i) => {
const unsignedArray = txns[i]
const signedArray = signedTxns.splice(0, txnArray.length)

if (!unsignedTxn) {
if (!unsignedArray) {
throw new Error('Failed to parse transaction array.')
}

return {
blob: new Uint8Array(Buffer.from(txn.blob.buffer)),
txID: unsignedTxn.txID,
signers: unsignedTxn.signers
}
return signedArray.map((signedTxn, index) => {
const usignedTxn = unsignedArray[index]

if (!usignedTxn) {
throw new Error('Failed to parse transaction array.')
}

return {
...usignedTxn,
blob: new Uint8Array(Buffer.from(signedTxn.blob.buffer))
}
})
})
} else {
throw new Error('')
}

return formated
}
Loading

0 comments on commit cea557e

Please sign in to comment.