Skip to content

Commit

Permalink
squiggle
Browse files Browse the repository at this point in the history
  • Loading branch information
barnjamin committed Dec 27, 2023
1 parent 7056e86 commit cc0027e
Show file tree
Hide file tree
Showing 16 changed files with 843 additions and 1,819 deletions.
622 changes: 0 additions & 622 deletions platforms/algorand/protocols/tokenBridge/src/_vaa.ts

This file was deleted.

132 changes: 0 additions & 132 deletions platforms/algorand/protocols/tokenBridge/src/apps.ts

This file was deleted.

76 changes: 23 additions & 53 deletions platforms/algorand/protocols/tokenBridge/src/assets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Chain, ChainId, toChainId } from "@wormhole-foundation/connect-sdk";
import { ChainId } from "@wormhole-foundation/connect-sdk";
import {
CHAIN_ID_ALGORAND,
TransactionSignerPair,
Expand All @@ -7,18 +7,15 @@ import {
Algodv2,
Transaction,
bigIntToBytes,
bytesToBigInt,
getApplicationAddress,
makeApplicationOptInTxnFromObject,
makePaymentTxnWithSuggestedParamsFromObject,
modelsv2,
signLogicSigTransaction,
modelsv2
} from "algosdk";
import { OptInResult, WormholeWrappedInfo } from "./types";
import { safeBigIntToNumber } from "./utilities";
import { calcLogicSigAccount, decodeLocalState } from "./apps";
import { hex } from "@wormhole-foundation/sdk-base/src/utils/encoding";
import { SEED_AMT } from "./constants";
import { StorageLsig } from "./storage";
import { TransactionSet, WormholeWrappedInfo } from "./types";
import { SEED_AMT, safeBigIntToNumber, decodeLocalState } from "./utilities";

const accountExistsCache = new Set<[bigint, string]>();

Expand Down Expand Up @@ -79,40 +76,6 @@ export async function getOriginalAssetOffAlgorand(
return retVal;
}

/**
* Returns an origin chain and asset address on {originChain} for a provided Wormhole wrapped address
* @param client Algodv2 client
* @param tokenBridgeId Application ID of the token bridge
* @param assetId Algorand asset index
* @returns Promise with the Algorand asset index or null
*/
export async function getWrappedAssetOnAlgorand(
client: Algodv2,
tokenBridgeId: bigint,
chain: ChainId | Chain,
contract: string,
): Promise<bigint | null> {
const chainId = toChainId(chain);
if (chainId === CHAIN_ID_ALGORAND) {
return bytesToBigInt(hex.decode(contract));
} else {
let { lsa, doesExist } = await calcLogicSigAccount(
client,
tokenBridgeId,
BigInt(chainId),
contract,
);
if (!doesExist) {
return null;
}
let asset: Uint8Array = await decodeLocalState(client, tokenBridgeId, lsa.address());
if (asset.length > 8) {
const tmp = Buffer.from(asset.slice(0, 8));
return tmp.readBigUInt64BE(0);
} else return null;
}
}

/**
* Calculates the logic sig account for the application
* @param client An Algodv2 client
Expand All @@ -122,32 +85,38 @@ export async function getWrappedAssetOnAlgorand(
* @param emitterId Emitter address
* @returns Address and array of TransactionSignerPairs
*/
export async function optIn(
export async function maybeOptInTx(
client: Algodv2,
senderAddr: string,
appId: bigint,
appIndex: bigint,
emitterId: string,
): Promise<OptInResult> {
storage: StorageLsig,
): Promise<TransactionSet> {
const appAddr: string = getApplicationAddress(appId);

// Check to see if we need to create this
const { doesExist, lsa } = await calcLogicSigAccount(client, appId, appIndex, emitterId);
const sigAddr: string = lsa.address();
const lsa = storage.lsig();
const storageAddress = lsa.address();

let exists = false;
try {
// TODO: check
await client.accountInformation(storageAddress).do();
exists = true;
} catch {}

let txs: TransactionSignerPair[] = [];
if (!doesExist) {
if (!exists) {
// These are the suggested params from the system
const params = await client.getTransactionParams().do();
const seedTxn = makePaymentTxnWithSuggestedParamsFromObject({
from: senderAddr,
to: sigAddr,
to: storageAddress,
amount: SEED_AMT,
suggestedParams: params,
});
seedTxn.fee = seedTxn.fee * 2;
txs.push({ tx: seedTxn, signer: null });
const optinTxn = makeApplicationOptInTxnFromObject({
from: sigAddr,
from: storageAddress,
suggestedParams: params,
appIndex: safeBigIntToNumber(appId),
rekeyTo: appAddr,
Expand All @@ -163,8 +132,9 @@ export async function optIn(

accountExistsCache.add([appId, lsa.address()]);
}

return {
addr: sigAddr,
address: storageAddress,
txs,
};
}
Expand Down
111 changes: 57 additions & 54 deletions platforms/algorand/protocols/tokenBridge/src/bigVarint.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,60 @@
// Forever grateful to https://github.com/joeltg/big-varint/blob/main/src/unsigned.ts
const LIMIT = BigInt(0x7f);

export function encodingLength(value: bigint): number {
let i = 0;

for (; value >= BigInt(0x80); i++) {
value >>= BigInt(7);
}

return i + 1;
}

export function encode(i: bigint, buffer?: ArrayBuffer, byteOffset?: number): Uint8Array {
if (i < BigInt(0)) {
throw new RangeError("value must be unsigned");
}

const byteLength = encodingLength(i);
buffer = buffer || new ArrayBuffer(byteLength);
byteOffset = byteOffset || 0;
if (buffer.byteLength < byteOffset + byteLength) {
throw new RangeError("the buffer is too small to encode the number at the offset");
}

const array = new Uint8Array(buffer, byteOffset);

let offset = 0;
while (LIMIT < i) {
array[offset++] = Number(i & LIMIT) | 0x80;
i >>= BigInt(7);
}

array[offset] = Number(i);

return array;
}

export function encodeHex(i: bigint, buffer?: ArrayBuffer, byteOffset?: number): string {
return Buffer.from(encode(i, buffer, byteOffset)).toString("hex");
}

export function decode(data: Uint8Array, offset = 0): bigint {
let i = BigInt(0);
let n = 0;
let b: number | undefined;
do {
b = data[offset + n];
if (b === undefined) {
throw new RangeError("offset out of range");

import { encoding } from "@wormhole-foundation/connect-sdk";

// Useful for encoding numbers as varints to patch TEAL binary
export const varint = {
encodingLength: (value: bigint) => {
let i = 0;
for (; value >= BigInt(0x80); i++) {
value >>= BigInt(7);
}
return i + 1;
},

encode: (i: bigint | number, buffer?: ArrayBuffer, byteOffset?: number) => {
if (typeof i === "number") i = BigInt(i);

const LIMIT = BigInt(0x7f);
if (i < BigInt(0)) {
throw new RangeError("value must be unsigned");
}

const byteLength = varint.encodingLength(i);
buffer = buffer || new ArrayBuffer(byteLength);
byteOffset = byteOffset || 0;
if (buffer.byteLength < byteOffset + byteLength) {
throw new RangeError("the buffer is too small to encode the number at the offset");
}

const array = new Uint8Array(buffer, byteOffset);

let offset = 0;
while (LIMIT < i) {
array[offset++] = Number(i & LIMIT) | 0x80;
i >>= BigInt(7);
}

i += BigInt(b & 0x7f) << BigInt(n * 7);
n++;
} while (0x80 <= b);
return i;
}
array[offset] = Number(i);

return array;
},
decode: (data: Uint8Array, offset = 0) => {
let i = BigInt(0);
let n = 0;
let b: number | undefined;
do {
b = data[offset + n];
if (b === undefined) {
throw new RangeError("offset out of range");
}

i += BigInt(b & 0x7f) << BigInt(n * 7);
n++;
} while (0x80 <= b);
return i;
},
encodeHex: (i: bigint | number, buffer?: ArrayBuffer, byteOffset?: number) => {
return encoding.hex.encode(varint.encode(i, buffer, byteOffset));
},
};
Loading

0 comments on commit cc0027e

Please sign in to comment.