Skip to content

Commit

Permalink
feat(PE-5758): add signer to ario class (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
atticusofsparta committed Mar 22, 2024
2 parents 7b18ab4 + 9d4bd9f commit 1b82077
Show file tree
Hide file tree
Showing 15 changed files with 1,550 additions and 617 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ coverage
.nyc_output
dist
.husky/_
cache

# IDEs and editors
.vscode
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This is the home of [ar.io] SDK. This SDK provides functionality for interacting
- [Typescript](#typescript)
- [ArIO Contract](#ario-contract)
- [APIs](#apis)
- [connect](#connectsigner)
- [getBalance](#getbalance-address-evaluationoptions-)
- [getBalances](#getbalances-evaluationoptions-)
- [getGateway](#getgateway-address-evaluationoptions-)
Expand All @@ -29,6 +30,7 @@ This is the home of [ar.io] SDK. This SDK provides functionality for interacting
- [Custom Contracts](#custom-contracts)
- [ANT Contracts](#arweave-name-tokens-ants)
- [APIs](#apis-1)
- [connect](#connectsigner)
- [getRecords](#getrecords-evaluationoptions-)
- [getOwner](#getowner-evaluationoptions-)
- [getControllers](#getcontrollers-evaluationoptions-)
Expand Down Expand Up @@ -171,6 +173,23 @@ The SDK provides TypeScript types. When you import the SDK in a TypeScript proje

### APIs

#### `connect(signer)`

Connects an `ArweaveSigner` or `ArConnectSigner` instance to the client for performing `writeInteraction` calls.
Supported only on clients configured with a `WarpContract` instance.

NOTE: if you have a client configured with a `RemoteContract` instance, it will be overriden with a `WarpContract` instance using the existing configuration of the `RemoteContract` instance when `connect` is executed.

```typescript
const arIO = new ArIO();

const browserSigner = new ArConnectSigner(window.arweaveWallet);
arIO.connect(browserSigner);

const nodeSigner = new ArweaveSigner(JWK);
arIO.connect(nodeSigner);
```

#### `getBalance({ address, evaluationOptions })`

Retrieves the balance of the specified wallet address.
Expand Down Expand Up @@ -581,6 +600,23 @@ The ANT contract client class exposes APIs relevant to compliant Arweave Name To

### APIs

#### `connect(signer)`

Connects an `ArweaveSigner` or `ArConnectSigner` instance to the client for performing `writeInteraction` calls.
Supported only on clients configured with a `WarpContract` instance.

NOTE: if you have a client configured with a `RemoteContract` instance, it will be overriden with a `WarpContract` instance using the existing configuration of the `RemoteContract` instance when `connect` is executed.

```typescript
const ant = new ANT();

const browserSigner = new ArConnectSigner(window.arweaveWallet);
ant.connect(browserSigner);

const nodeSigner = new ArweaveSigner(JWK);
ant.connect(nodeSigner);
```

#### `getOwner({ evaluationOptions })`

Returns the owner of the configured ANT contract.
Expand Down
6 changes: 5 additions & 1 deletion examples/node/index.cjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
const Arweave = require('arweave');
const {
ArIO,
ARNS_TESTNET_REGISTRY_TX,
} = require('../../lib/cjs/node/index.js');
const { ArweaveSigner } = require('arbundles');

(async () => {
const arIO = new ArIO();
const jwk = await Arweave.init({}).wallets.generate();
const signer = new ArweaveSigner(jwk);
const arIO = new ArIO({ signer });
// testnet gateways
const testnetGateways = await arIO.getGateways();
const protocolBalance = await arIO.getBalance({
Expand Down
7 changes: 6 additions & 1 deletion examples/node/index.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { ArweaveSigner } from 'arbundles';
import Arweave from 'arweave';

import { ARNS_TESTNET_REGISTRY_TX, ArIO } from '../../lib/esm/node/index.js';

(async () => {
const arIO = new ArIO();
const jwk = await Arweave.init({}).wallets.generate();
const signer = new ArweaveSigner(jwk);
const arIO = new ArIO({ signer });
// testnet gateways
const testnetGateways = await arIO.getGateways();
const protocolBalance = await arIO.getBalance({
Expand Down
8 changes: 6 additions & 2 deletions examples/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,14 @@ <h1 class="text-textPrimary w-full font-bold">View Distribution Data</h1>
</div>

<script type="module">
import { ArconnectSigner } from 'https://unpkg.com/arbundles@0.11.0/build/web/esm/webIndex.js';
import Arweave from 'https://unpkg.com/arweave@1.14.4/web/index.js';

import { ArIO } from './web.bundle.min.js';

// set up our client
const arIO = new ArIO();
const arweave = Arweave.init({});
const signer = new ArconnectSigner(window['arweaveWallet'], arweave);
const arIO = new ArIO({ signer });

// fetch data on page load
async function init() {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"typescript": "^5.1.6"
},
"dependencies": {
"arbundles": "0.11.0",
"arweave": "^1.14.4",
"axios": "1.4.0",
"setimmediate": "^1.0.5",
Expand Down
48 changes: 39 additions & 9 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ArconnectSigner, ArweaveSigner } from 'arbundles';

import {
ANTRecord,
ANTState,
Expand All @@ -32,17 +34,21 @@ export type SortKey = string;
export type WalletAddress = string;

// TODO: append this with other configuration options (e.g. local vs. remote evaluation)
export type ContractConfiguration =
export type ContractSigner = ArweaveSigner | ArconnectSigner;
export type ContractConfiguration = {
signer?: ContractSigner; // TODO: optionally allow JWK in place of signer
} & (
| {
contract?: SmartWeaveContract<unknown>;
contract?: BaseContract<unknown> & ReadContract;
}
| {
contractTxId: string;
};
}
);

export function isContractConfiguration<T>(
config: ContractConfiguration,
): config is { contract: SmartWeaveContract<T> } {
): config is { contract: BaseContract<T> & ReadContract } {
return 'contract' in config;
}

Expand All @@ -62,19 +68,44 @@ export type EvaluationParameters<T = NonNullable<unknown>> = {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} & T;

export interface BaseContract<T> {
getState(params: EvaluationParameters): Promise<T>;
connect(signer: ContractSigner): this;
}

export interface ReadContract {
readInteraction<Input, State>({
functionName,
inputs,
evaluationOptions,
}: EvaluationParameters<{
functionName: string;
inputs?: Input;
}>): Promise<State>;
}

export interface WriteContract {
writeInteraction<Input, State>({
functionName,
inputs,
evaluationOptions,
}: EvaluationParameters<{
functionName: string;
inputs: Input;
}>): Promise<State>;
}

export interface SmartWeaveContract<T> {
getContractState(params: EvaluationParameters): Promise<T>;
readInteraction<I, K>({
functionName,
inputs,
evaluationOptions,
}: EvaluationParameters<{ functionName: string; inputs?: I }>): Promise<K>;
// TODO: write interaction
}

// TODO: extend with additional methods
export interface ArIOContract {
getState({ evaluationOptions }: EvaluationParameters): Promise<ArIOState>;
export interface ArIOContract extends BaseContract<ArIOState> {
getGateway({
address,
evaluationOptions,
Expand Down Expand Up @@ -138,8 +169,7 @@ export interface ArIOContract {
}>): Promise<ArNSAuctionData>;
}

export interface ANTContract {
getState({ evaluationOptions }: EvaluationParameters): Promise<ANTState>;
export interface ANTContract extends BaseContract<ANTState> {
getRecord({
domain,
evaluationOptions,
Expand Down
55 changes: 35 additions & 20 deletions src/common/ant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ import {
ANTContract,
ANTRecord,
ANTState,
BaseContract,
ContractConfiguration,
ContractSigner,
EvaluationOptions,
EvaluationParameters,
SmartWeaveContract,
isContractConfiguration,
isContractTxIdConfiguration,
} from '../types.js';
import { RemoteContract } from './contracts/remote-contract.js';
import { WarpContract } from './index.js';

export class ANT implements ANTContract {
private contract: SmartWeaveContract<ANTState>;
export class ANT implements ANTContract, BaseContract<ANTState> {
private contract: BaseContract<ANTState>;
private signer: ContractSigner | undefined;

constructor(config: ContractConfiguration) {
constructor({ signer, ...config }: ContractConfiguration) {
this.signer = signer;
if (isContractConfiguration<ANTState>(config)) {
this.contract = config.contract;
} else if (isContractTxIdConfiguration(config)) {
Expand All @@ -40,13 +44,24 @@ export class ANT implements ANTContract {
}
}

connect(signer: ContractSigner): this {
this.signer = signer;
if (this.contract instanceof RemoteContract) {
const config = this.contract.configuration();
this.contract = new WarpContract<ANTState>({
...config,
signer,
});
}
this.contract.connect(this.signer);

return this;
}
/**
* Returns the current state of the contract.
*/
async getState({
evaluationOptions,
}: EvaluationParameters = {}): Promise<ANTState> {
const state = await this.contract.getContractState({ evaluationOptions });
async getState(params: EvaluationParameters = {}): Promise<ANTState> {
const state = await this.contract.getState(params);
return state;
}

Expand All @@ -62,53 +77,53 @@ export class ANT implements ANTContract {
evaluationOptions,
}: {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} = {}): Promise<Record<string, ANTRecord>> {
const state = await this.contract.getContractState({ evaluationOptions });
}): Promise<Record<string, ANTRecord>> {
const state = await this.contract.getState({ evaluationOptions });
return state.records;
}

async getOwner({
evaluationOptions,
}: {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} = {}): Promise<string> {
const state = await this.contract.getContractState({ evaluationOptions });
}): Promise<string> {
const state = await this.contract.getState({ evaluationOptions });
return state.owner;
}

async getControllers({
evaluationOptions,
}: {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} = {}): Promise<string[]> {
const state = await this.contract.getContractState({ evaluationOptions });
}): Promise<string[]> {
const state = await this.contract.getState({ evaluationOptions });
return state.controllers;
}

async getName({
evaluationOptions,
}: {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} = {}): Promise<string> {
const state = await this.contract.getContractState({ evaluationOptions });
}): Promise<string> {
const state = await this.contract.getState({ evaluationOptions });
return state.name;
}

async getTicker({
evaluationOptions,
}: {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} = {}): Promise<string> {
const state = await this.contract.getContractState({ evaluationOptions });
}): Promise<string> {
const state = await this.contract.getState({ evaluationOptions });
return state.ticker;
}

async getBalances({
evaluationOptions,
}: {
evaluationOptions?: EvaluationOptions | Record<string, never> | undefined;
} = {}): Promise<Record<string, number>> {
const state = await this.contract.getContractState({ evaluationOptions });
}): Promise<Record<string, number>> {
const state = await this.contract.getState({ evaluationOptions });
return state.balances;
}

Expand Down

0 comments on commit 1b82077

Please sign in to comment.