-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add CustomContract class using abitype
- Loading branch information
Showing
10 changed files
with
325 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { providers } from 'ethers'; | ||
import 'cross-fetch/dist/node-polyfill.js'; | ||
import { erc20Abi } from 'abitype/abis'; | ||
|
||
import { type Address } from 'abitype'; | ||
import { | ||
ColonyNetwork, | ||
ColonyRpcEndpoint, | ||
CustomContract, | ||
toEth, | ||
} from '../../src/index.js'; | ||
|
||
const provider = new providers.JsonRpcProvider(ColonyRpcEndpoint.ArbitrumOne); | ||
|
||
// Create a custom instance of the USDC token on Arbitrum One | ||
const start = async () => { | ||
const colonyNetwork = new ColonyNetwork(provider); | ||
const usdc = new CustomContract( | ||
colonyNetwork, | ||
'0xaf88d065e77c8cC2239327C5EDb3A432268e5831', | ||
erc20Abi, | ||
); | ||
const metaColony = await colonyNetwork.getMetaColony(); | ||
const { address } = metaColony; | ||
const [funds] = await usdc.read('balanceOf', [address as Address]); | ||
console.info( | ||
`${toEth(funds)} CLNY in root team of MetaColony with address: ${address}`, | ||
); | ||
}; | ||
|
||
start(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { | ||
ColonyNetworkAddress, | ||
MetaTxBroadCasterEndpoint, | ||
ReputationOracleEndpoint, | ||
} from '@colony/core'; | ||
import { type ContractInterface, Contract, Signer } from 'ethers'; | ||
import { IpfsMetadata, Network, type SignerOrProvider } from '../index.js'; | ||
import { | ||
type ColonyNetworkConfig, | ||
type ColonyNetworkOptions, | ||
} from './ColonyNetwork.js'; | ||
import { type IColonyNetwork } from '../contracts/IColonyNetwork.js'; | ||
|
||
export class CustomColonyNetwork { | ||
private networkContract: IColonyNetwork; | ||
|
||
/** Configuration of the ColonyNetwork for later use */ | ||
/** @internal */ | ||
config: ColonyNetworkConfig; | ||
|
||
/** The IPFS adapter for Metadata. Defaults to a read-only adapter */ | ||
ipfs: IpfsMetadata; | ||
|
||
/** The network the client is connected to. Defaults to Gnosis chain */ | ||
network: Network; | ||
|
||
/** | ||
* An ethers.js [Signer](https://docs.ethers.org/v5/api/signer/#Signer) or [Provider](https://docs.ethers.org/v5/api/providers/). | ||
* | ||
* E.g. a [Wallet](https://docs.ethers.org/v5/api/signer/#Wallet) or a [Web3Provider](https://docs.ethers.org/v5/api/providers/other/#Web3Provider) (MetaMask) | ||
*/ | ||
signerOrProvider: SignerOrProvider; | ||
|
||
/** | ||
* Creates a new custom instance of the custom ColonyNetwork | ||
* | ||
* @param signerOrProvider - An _ethers_ compatible Signer or Provider instance | ||
* @param abi - JSON ABI of the custom ColonyNetwork contract | ||
* @param options - Optional custom {@link ColonyNetworkOptions} | ||
* @returns A ColonyNetwork abstraction instance | ||
*/ | ||
constructor( | ||
signerOrProvider: SignerOrProvider, | ||
abi: ContractInterface, | ||
options?: ColonyNetworkOptions, | ||
) { | ||
this.network = options?.network || Network.Gnosis; | ||
this.ipfs = new IpfsMetadata(options?.ipfsAdapter); | ||
this.config = { | ||
metaTxBroadcasterEndpoint: | ||
options?.metaTxBroadcasterEndpoint || | ||
MetaTxBroadCasterEndpoint[this.network], | ||
reputationOracleEndpoint: | ||
options?.reputationOracleEndpoint || | ||
ReputationOracleEndpoint[this.network], | ||
}; | ||
// Here we need to create the contract with ethers | ||
this.networkContract = new Contract( | ||
options?.customNetworkAddress || ColonyNetworkAddress[this.network], | ||
abi, | ||
signerOrProvider, | ||
) as IColonyNetwork; | ||
this.signerOrProvider = signerOrProvider; | ||
} | ||
|
||
getSigner(): Signer { | ||
if (!(this.signerOrProvider instanceof Signer)) { | ||
throw new Error('Need a signer to create a transaction'); | ||
} | ||
return this.signerOrProvider; | ||
} | ||
|
||
getInternalNetworkContract() { | ||
return this.networkContract; | ||
} | ||
} | ||
|
||
export default CustomColonyNetwork; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { | ||
type Abi, | ||
type AbiParametersToPrimitiveTypes, | ||
type Address, | ||
type ExtractAbiFunction, | ||
type ExtractAbiFunctionNames, | ||
} from 'abitype'; | ||
import { Contract, type ContractInterface } from 'ethers'; | ||
import { | ||
type ColonyNetwork, | ||
type ContractReceipt, | ||
type EventData, | ||
type MetaTxBaseContract, | ||
type TxConfig, | ||
} from '../index.js'; | ||
import type CustomColonyNetwork from './CustomColonyNetwork.js'; | ||
import CustomTxCreator from '../TxCreator/CustomTxCreator.js'; | ||
|
||
export class CustomContract<A extends Abi> { | ||
private abi: A; | ||
|
||
private colonyNetwork: ColonyNetwork | CustomColonyNetwork; | ||
|
||
private contract: MetaTxBaseContract; | ||
|
||
address: Address; | ||
|
||
/** | ||
* Creates a new instance of a custom contract | ||
* | ||
* This is your main entry point to talk to the Colony Network Smart Contracts. | ||
* From here you should be able to instantiate all the required instances for Colonies and their extensions. | ||
* | ||
* @param colonyNetwork - {@link ColonyNetwork} instance | ||
* @param address - Address of the deployed contract | ||
* @param abi - JSON ABI of the contract | ||
* @returns A CustomContract instance | ||
*/ | ||
constructor( | ||
colonyNetwork: ColonyNetwork | CustomColonyNetwork, | ||
address: Address, | ||
abi: A, | ||
) { | ||
this.address = address; | ||
this.abi = abi; | ||
|
||
// We do a little bit of casting to make ethers happy with the abitype types | ||
this.contract = new Contract( | ||
address, | ||
this.abi as unknown as ContractInterface, | ||
colonyNetwork.signerOrProvider, | ||
) as unknown as MetaTxBaseContract; | ||
this.colonyNetwork = colonyNetwork; | ||
} | ||
|
||
/** | ||
* Creates a new {@link CustomTxCreator} for custom, permissioned transactions or metatransactions | ||
* | ||
* @param method - The transaction method to execute on the contract | ||
* @param args - The arguments for the method | ||
* @param eventData - A function that extracts the relevant event data from the {@link ContractReceipt} | ||
* @param txConfig - More configuration options, like {@link MetadataType} if the event contains metadata or if methods are unsupported | ||
* @returns A {@link CustomTxCreator} | ||
*/ | ||
createTxCreator< | ||
M extends ExtractAbiFunctionNames<A, 'payable' | 'nonpayable'>, | ||
E extends EventData, | ||
>( | ||
method: M, | ||
args: AbiParametersToPrimitiveTypes< | ||
ExtractAbiFunction<A, M>['inputs'], | ||
'inputs' | ||
>, | ||
eventData?: (receipt: ContractReceipt) => Promise<E>, | ||
txConfig?: TxConfig, | ||
) { | ||
return new CustomTxCreator<A, M, E>({ | ||
colonyNetwork: this.colonyNetwork, | ||
contract: this.contract, | ||
method, | ||
args, | ||
eventData, | ||
txConfig, | ||
}); | ||
} | ||
|
||
/** | ||
* Read a contract value | ||
* | ||
* @param method - The pure/view method to read from the contract | ||
* @param args - The arguments for the method | ||
* @returns A promise resolving into the specific type for the contract return value | ||
*/ | ||
async read<M extends ExtractAbiFunctionNames<A, 'pure' | 'view'>>( | ||
method: M, | ||
args: AbiParametersToPrimitiveTypes< | ||
ExtractAbiFunction<A, M>['inputs'], | ||
'inputs' | ||
>, | ||
): Promise< | ||
AbiParametersToPrimitiveTypes< | ||
ExtractAbiFunction<A, M>['outputs'], | ||
'outputs' | ||
> | ||
> { | ||
// A little typecasting to make ethers happy | ||
const customArgs = args as unknown[]; | ||
const contract = this.contract as unknown as Record< | ||
string, | ||
(...args: unknown[]) => Promise<unknown> | ||
>; | ||
const result = contract[method](...customArgs) as Promise< | ||
AbiParametersToPrimitiveTypes< | ||
ExtractAbiFunction<A, M>['outputs'], | ||
'outputs' | ||
> | ||
>; | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { | ||
type ExtractAbiFunction, | ||
type AbiParametersToPrimitiveTypes, | ||
type Abi, | ||
type ExtractAbiFunctionNames, | ||
} from 'abitype'; | ||
|
||
import { type ContractReceipt } from 'ethers'; | ||
|
||
import { type EventData, type TxConfig } from './TxCreator.js'; | ||
import type CustomColonyNetwork from '../ColonyNetwork/CustomColonyNetwork.js'; | ||
import { | ||
type ColonyNetwork, | ||
type MetaTxBaseContract, | ||
MetaTxCreator, | ||
} from '../index.js'; | ||
|
||
/** | ||
* Create transactions for custom contracts | ||
* | ||
* The `CustomTxCreator` allows for a simple API to cover all the different cases of transactions within the Colony Network. | ||
* This TxCreator works specifically for custom contracts that are not (yet) part of the Colony SDK. | ||
* | ||
* ## Creating a transaction | ||
* | ||
* - [[CustomTxCreator.tx]]: force a Colony transaction, knowing you have the permissions to do so | ||
* - [[CustomTxCreator.metaTx]]: same as `tx()`, but send as a gasless metatransaction | ||
*/ | ||
class CustomTxCreator< | ||
A extends Abi, | ||
M extends ExtractAbiFunctionNames<A, 'payable' | 'nonpayable'>, | ||
E extends EventData, | ||
> extends MetaTxCreator<MetaTxBaseContract, M, E> { | ||
constructor({ | ||
colonyNetwork, | ||
contract, | ||
method, | ||
args, | ||
eventData, | ||
txConfig, | ||
}: { | ||
colonyNetwork: ColonyNetwork | CustomColonyNetwork; | ||
contract: MetaTxBaseContract; | ||
method: M; | ||
args: AbiParametersToPrimitiveTypes< | ||
ExtractAbiFunction<A, M>['inputs'], | ||
'inputs' | ||
>; | ||
eventData?: (receipt: ContractReceipt) => Promise<E>; | ||
txConfig?: TxConfig; | ||
}) { | ||
const customArgs = args as unknown[]; | ||
super({ | ||
colonyNetwork, | ||
contract, | ||
method, | ||
args: customArgs, | ||
eventData, | ||
txConfig, | ||
}); | ||
} | ||
} | ||
|
||
export default CustomTxCreator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.