Skip to content
This repository has been archived by the owner on Sep 4, 2024. It is now read-only.

Commit

Permalink
Feat: Arconnect support (#110)
Browse files Browse the repository at this point in the history
* feat: ✨ web: add Arconnect support

* fix: 🐛 misc: fix basicTest
  • Loading branch information
JesseTheRobot authored Oct 15, 2023
1 parent 549560a commit eda7b0e
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 111 deletions.
8 changes: 4 additions & 4 deletions scripts/basicTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@ async function main() {
if (profiling) console.profile();
const keys = JSON.parse(readFileSync("wallet.json").toString());

const nodeUrl = "http://devnet.irys.network";
const nodeUrl = "http://devnet.irys.xyz";
const testFolder = "testFolder";

const { key, providerUrl } = keys.testnet.ethereum;

// let irys = await irys.init({ url: nodeUrl, currency: "aptos", publicKey: account.pubKey().toString(), signingFunction });
// let irys = irys.init({ url: nodeUrl, currency: "aptos", privateKey: key })

const irys = new Irys({ url: nodeUrl, currency: "ethereum", wallet: key, config: { providerUrl } });
const irys = new Irys({ url: nodeUrl, token: "ethereum", key: key, config: { providerUrl } });
await irys.ready();
console.log(irys.address);

let res;
let tx;

console.log(`balance: ${await irys.getLoadedBalance()}`);
const bAddress = await irys.utils.getBundlerAddress(irys.currency);
const bAddress = await irys.utils.getBundlerAddress(irys.token);
console.log(`irys address: ${bAddress}`);

tx = irys.createTransaction("Hello, world!", { tags: [{ name: "Content-type", value: "text/plain" }] });
Expand All @@ -52,7 +52,7 @@ async function main() {
res = await transaction.upload({ getReceiptSignature: false });

const signingInfo = await transaction.getSignatureData();
const signed = await irys.currencyConfig.sign(signingInfo);
const signed = await irys.tokenConfig.sign(signingInfo);
transaction.setSignature(Buffer.from(signed));

console.log(transaction.id);
Expand Down
2 changes: 1 addition & 1 deletion src/web/irys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class WebIrys extends Irys {
this.tokenConfig = getTokenConfig({
irys: this,
token: token.toLowerCase(),
wallet: wallet?.provider,
wallet: wallet?.provider ?? wallet,
providerUrl: config?.providerUrl ?? wallet?.rpcUrl,
contractAddress: config?.contractAddress,
providerName: wallet?.name,
Expand Down
219 changes: 115 additions & 104 deletions src/web/tokens/arweave.ts
Original file line number Diff line number Diff line change
@@ -1,117 +1,128 @@
// import { ArconnectSigner } from "arbundles";
// import BigNumber from "bignumber.js";
// import crypto from "crypto";
// import type { CurrencyConfig, Tx } from "../../common/types";
// import base64url from "base64url";
// import BaseNodeCurrency from "../currency";
// import { Arweave } from "../utils";
import { ArconnectSigner } from "arbundles";
import BigNumber from "bignumber.js";
import crypto from "crypto";
import type { TokenConfig, Tx } from "../../common/types";
import base64url from "base64url";
import { Arweave } from "../utils";

// // eslint-disable-next-line @typescript-eslint/no-unused-vars
// import type * as _ from "arconnect";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type * as _ from "arconnect";
import BaseWebToken from "../token";

// export default class ArweaveConfig extends BaseNodeCurrency {
// protected declare providerInstance: Arweave;
// opts?: { provider?: "arconnect" | "arweave.app"; network?: string };
// protected declare wallet: Window["arweaveWallet"];
// protected signerInstance: ArconnectSigner;
// constructor(config: CurrencyConfig) {
// super(config);
// this.base = ["winston", 1e12];
// this.needsFee = true;
// }
export default class ArweaveConfig extends BaseWebToken {
protected declare providerInstance: Arweave;
public isSlow = true;
opts?: { provider?: "arconnect" | "arweave.app"; network?: string };
protected declare wallet: Window["arweaveWallet"];
protected signerInstance: ArconnectSigner;
constructor(config: TokenConfig) {
super(config);
this.base = ["winston", 1e12];
this.needsFee = true;
}

// private async getProvider(): Promise<Arweave> {
// if (!this.providerInstance) {
// const purl = new URL(this.providerUrl ?? "https://arweave.net");
// let config;
// try {
// config = this.wallet.getArweaveConfig();
// } catch (e) {}
// this.providerInstance = Arweave.init(
// config ?? {
// host: purl.hostname,
// protocol: purl.protocol.replaceAll(":", "").replaceAll("/", ""),
// port: purl.port,
// network: this?.opts?.network,
// },
// );
// }
// return this.providerInstance;
// }
private getProvider(): Arweave {
if (!this.providerInstance) {
const purl = new URL(this.providerUrl ?? "https://arweave.net");
// let config;
// try {
// config = this.wallet.getArweaveConfig();
// } catch (e) {}
this.providerInstance = Arweave.init(
/* config ?? */ {
url: purl,
network: this?.opts?.network,
},
);
}
return this.providerInstance;
}

// async getTx(txId: string): Promise<Tx> {
// const arweave = await this.getProvider();
// const txs = await arweave.transactions.getStatus(txId);
// let tx;
// if (txs.status === 200) {
// tx = await arweave.transactions.get(txId);
// }
// const confirmed = txs.status !== 202 && (txs.confirmed?.number_of_confirmations ?? 0) >= this.minConfirm;
// let owner;
// if (tx?.owner) {
// owner = this.ownerToAddress(tx.owner);
// }
// return {
// from: owner ?? undefined,
// to: tx?.target ?? undefined,
// amount: new BigNumber(tx?.quantity ?? 0),
// pending: txs.status === 202,
// confirmed,
// };
// }
async getTx(txId: string): Promise<Tx> {
const arweave = await this.getProvider();
const txs = await arweave.transactions.getStatus(txId);
let tx;
if (txs.status === 200) {
tx = await arweave.transactions.get(txId);
}
const confirmed = txs.status !== 202 && (txs.confirmed?.number_of_confirmations ?? 0) >= this.minConfirm;
let owner;
if (tx?.owner) {
owner = this.ownerToAddress(tx.owner);
}
return {
from: owner ?? undefined,
to: tx?.target ?? undefined,
amount: new BigNumber(tx?.quantity ?? 0),
pending: txs.status === 202,
confirmed,
};
}

// ownerToAddress(owner: any): string {
// return Arweave.utils.bufferTob64Url(
// crypto
// .createHash("sha256")
// .update(Arweave.utils.b64UrlToBuffer(Buffer.isBuffer(owner) ? base64url(owner) : owner))
// .digest(),
// );
// }
ownerToAddress(owner: any): string {
return Arweave.utils.bufferTob64Url(
crypto
.createHash("sha256")
.update(Arweave.utils.b64UrlToBuffer(Buffer.isBuffer(owner) ? base64url(owner) : owner))
.digest(),
);
}

// async sign(data: Uint8Array): Promise<Uint8Array> {
// return this.getSigner().sign(data);
// }
async sign(data: Uint8Array): Promise<Uint8Array> {
return this.getSigner().sign(data);
}

// getSigner(): ArconnectSigner {
// if (this.signerInstance) return this.signerInstance;
// switch (this?.opts?.provider ?? "arconnect") {
// case "arconnect":
// this.signerInstance = new ArconnectSigner(this.wallet);
// }
// return this.signerInstance;
// }
getSigner(): ArconnectSigner {
if (this.signerInstance) return this.signerInstance;
switch (this?.opts?.provider ?? "arconnect") {
case "arconnect":
this.signerInstance = new ArconnectSigner(this.wallet, this.getProvider());
}
return this.signerInstance;
}

// async verify(pub: any, data: Uint8Array, signature: Uint8Array): Promise<boolean> {
// if (Buffer.isBuffer(pub)) {
// pub = pub.toString();
// }
// return Arweave.crypto.verify(pub, data, signature);
// }
async verify(pub: any, data: Uint8Array, signature: Uint8Array): Promise<boolean> {
if (Buffer.isBuffer(pub)) {
pub = pub.toString();
}
return this.getProvider().crypto.verify(pub, data, signature);
}

// async getCurrentHeight(): Promise<BigNumber> {
// return (await this.getProvider()).network.getInfo().then((r) => new BigNumber(r.height));
// }
async getCurrentHeight(): Promise<BigNumber> {
return (await this.getProvider()).network.getInfo().then((r) => new BigNumber(r.height));
}

// async getFee(amount: BigNumber.Value, to?: string): Promise<BigNumber> {
// return new BigNumber(await (await this.getProvider()).transactions.getPrice(new BigNumber(amount).toNumber(), to)).integerValue(
// BigNumber.ROUND_CEIL,
// );
// }
async getFee(amount: BigNumber.Value, to?: string): Promise<BigNumber> {
return new BigNumber(await (await this.getProvider()).transactions.getPrice(new BigNumber(amount).toNumber(), to)).integerValue(
BigNumber.ROUND_CEIL,
);
}

// async sendTx(data: any): Promise<any> {
// return await (await this.getProvider()).transactions.post(data);
// }
async sendTx(data: any): Promise<any> {
return await (await this.getProvider()).transactions.post(data);
}

// async createTx(amount: BigNumber.Value, to: string, fee?: string): Promise<{ txId: string | undefined; tx: any }> {
// const arweave = await this.getProvider();
// const tx = await this.wallet.sign(await arweave.createTransaction({ quantity: new BigNumber(amount).toString(), reward: fee, target: to }));
// return { txId: tx.id, tx };
// }
async createTx(amount: BigNumber.Value, to: string, fee?: string): Promise<{ txId: string | undefined; tx: any }> {
const arweave = await this.getProvider();
const atx = await arweave.createTransaction({ quantity: new BigNumber(amount).toString(), reward: fee?.toString(), target: to });
// @ts-expect-error override
atx.merkle = undefined;
// @ts-expect-error override
atx.deepHash = undefined;
// @ts-expect-error types
const tx = await this.wallet.sign(atx);
return { txId: tx.id, tx };
}

// async getPublicKey(): Promise<string> {
// const signer = this.getSigner();
// await signer.setPublicKey();
// return Arweave.utils.bufferTob64Url(signer.publicKey);
// }
// }
async getPublicKey(): Promise<string> {
const signer = this.getSigner();
await signer.setPublicKey();
return Arweave.utils.bufferTob64Url(signer.publicKey);
}

public async ready(): Promise<void> {
const pubKey = await this.getPublicKey();
const address = this.ownerToAddress(pubKey);
this._address = address;
}
}
10 changes: 10 additions & 0 deletions src/web/tokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { EthereumEthersV5 } from "../providers/ethereum/ethersv5";
import { EthereumEthersV6 } from "../providers/ethereum/ethersv6";
import type { TokenConfig } from "src/common/types";
import type BaseWebToken from "../token";
import ArweaveConfig from "./arweave";

export default function getTokenConfig(config: {
irys: WebIrys;
Expand Down Expand Up @@ -121,6 +122,15 @@ export default function getTokenConfig(config: {
providerUrl: config.providerUrl ?? "https://fullnode.mainnet.aptoslabs.com/v1",
wallet: config.wallet,
});
case "arweave":
return new ArweaveConfig({
irys: config.irys,
name: "arweave",
ticker: "AR",
providerUrl: config.providerUrl ?? "https://arweave.net",
wallet: config.wallet,
});

default:
throw new Error(`Unknown/Unsupported token ${config.token}`);
}
Expand Down
4 changes: 2 additions & 2 deletions src/web/utils.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { createData, DataItem, deepHash, stringToBuffer, getCryptoDriver, bundleAndSignData /* Arweave */ } from "arbundles/web";
export { createData, DataItem, deepHash, stringToBuffer, getCryptoDriver, bundleAndSignData /* Arweave */ };
import { createData, DataItem, deepHash, stringToBuffer, getCryptoDriver, bundleAndSignData, Arweave } from "arbundles/web";
export { createData, DataItem, deepHash, stringToBuffer, getCryptoDriver, bundleAndSignData, Arweave };

0 comments on commit eda7b0e

Please sign in to comment.