Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/itchy-pants-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@audius/eth': major
---

Release 1.0.0

- All contracts now simply export their ABIs and addresses.
- No viem dependency required.
- Treeshakable.
- Added examples and documentation.
2,023 changes: 6 additions & 2,017 deletions package-lock.json

Large diffs are not rendered by default.

113 changes: 112 additions & 1 deletion packages/eth/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,114 @@
# `@audius/eth`

A Typescript package for interacting with the Audius Governance and Staking [Ethereum Contracts](../../eth-contracts/).
Typed ABIs and production addresses for the [Audius Ethereum contracts](../../eth-contracts/). Designed for use with [viem](https://viem.sh/) and fully tree-shakable — import only the contracts you need.

## Installation

```bash
npm install @audius/eth viem
```

## Usage

Each contract export is a plain object with `abi` and `address`:

```ts
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { Staking } from '@audius/eth'

const client = createPublicClient({
chain: mainnet,
transport: http()
})

const totalStaked = await client.readContract({
...Staking,
functionName: 'totalStaked'
})
```

### Check pending rewards claim

```ts
import { ClaimsManager } from '@audius/eth'

const isPending = await client.readContract({
...ClaimsManager,
functionName: 'claimPending',
args: ['0xYourServiceProviderAddress']
})
```

### Read a governance proposal

```ts
import { Governance } from '@audius/eth'

const proposal = await client.readContract({
...Governance,
functionName: 'getProposalById',
args: [1n]
})
```

### Look up service provider endpoints

```ts
import { ServiceProviderFactory, VALIDATOR_SERVICE_TYPE } from '@audius/eth'

// Get the total number of validators
const total = await client.readContract({
...ServiceProviderFactory,
functionName: 'getTotalServiceTypeProviders',
args: [VALIDATOR_SERVICE_TYPE]
})

// Get the endpoint info for the first one
const info = await client.readContract({
...ServiceProviderFactory,
functionName: 'getServiceEndpointInfo',
args: [VALIDATOR_SERVICE_TYPE, 1n]
})
```

### EIP-2612 permit (gasless approval)

`AudiusToken` and `AudiusWormhole` include `domain` and `types` for EIP-712 signing:

```ts
import { AudiusToken } from '@audius/eth'

const signature = await walletClient.signTypedData({
domain: {
...AudiusToken.domain,
chainId: 1,
verifyingContract: AudiusToken.address
},
types: AudiusToken.types,
primaryType: 'Permit',
message: {
owner: '0x...',
spender: '0x...',
value: 1000000000000000000n,
nonce: 0n,
deadline: 99999999999n
}
})
```

## Contracts

| Export | Description |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `AudiusToken` | The AUDIO ERC-20 token. Mintable, pausable, burnable. Supports EIP-2612 `permit()`. |
| `AudiusWormhole` | Sends AUDIO cross-chain via Wormhole with meta-transaction support. |
| `ClaimsManager` | Periodic minting and distribution of AUDIO staking rewards. |
| `DelegateManager` | Delegation of AUDIO tokens to service providers with lockup periods. |
| `EthRewardsManager` | Transfers AUDIO rewards from Ethereum to Solana via Wormhole. |
| `Governance` | On-chain governance: proposals, stake-weighted voting, execution. |
| `Registry` | Central directory mapping contract names to addresses. |
| `ServiceProviderFactory` | Registration and staking for discovery nodes and content nodes. |
| `ServiceTypeManager` | Registry of valid service types and their versions. |
| `Staking` | Core staking contract holding all staked AUDIO with checkpointing. |
| `TrustedNotifierManager` | Registry of trusted notifier entities. |
4 changes: 1 addition & 3 deletions packages/eth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,5 @@
"url": "https://github.com/AudiusProject/apps/issues"
},
"homepage": "https://github.com/AudiusProject/apps/tree/main/packages/eth",
"dependencies": {
"viem": "2.21.21"
}
"sideEffects": false
}
27 changes: 16 additions & 11 deletions packages/eth/src/audius-token/audiusToken.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type { TypedData } from 'viem'

import { abi } from './abi'

export type AudiusTokenTypes = typeof AudiusToken.types
export class AudiusToken {
public static readonly abi = abi

public static readonly address =
'0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998' as const

public static readonly types = {
/**
* The AUDIO ERC-20 token contract.
* Initial supply of 1 billion tokens (18 decimals).
* Supports EIP-2612 gasless `permit()` approvals.
*/
export const AudiusToken = {
abi,
address: '0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998' as const,
domain: {
name: 'Audius',
version: '1'
} as const,
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
Expand All @@ -23,5 +26,7 @@ export class AudiusToken {
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
} as const satisfies TypedData
} as const
}

export type AudiusTokenTypes = typeof AudiusToken.types
1 change: 0 additions & 1 deletion packages/eth/src/audius-token/index.ts

This file was deleted.

22 changes: 11 additions & 11 deletions packages/eth/src/audius-wormhole/audiusWormhole.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { type TypedData } from 'viem'

import { abi } from './abi'

export type AudiusWormholeTypes = typeof AudiusWormhole.types

/**
* Contract that can be permitted to send tokens through the Wormhole Portal
* on a user's behalf. Not to be confused with the standard Wormhole contracts,
* nor to be confused with wAUDIO (the AudiusToken on Solana).
*/
export class AudiusWormhole {
public static readonly abi = abi

public static readonly address = '0x6E7a1F7339bbB62b23D44797b63e4258d283E095'

public static readonly types = {
export const AudiusWormhole = {
abi,
address: '0x6E7a1F7339bbB62b23D44797b63e4258d283E095' as const,
domain: {
name: 'AudiusWormholeClient',
version: '1'
} as const,
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
Expand All @@ -30,5 +28,7 @@ export class AudiusWormhole {
{ name: 'nonce', type: 'uint32' },
{ name: 'deadline', type: 'uint256' }
]
} as const satisfies TypedData
} as const
}

export type AudiusWormholeTypes = typeof AudiusWormhole.types
1 change: 0 additions & 1 deletion packages/eth/src/audius-wormhole/index.ts

This file was deleted.

94 changes: 8 additions & 86 deletions packages/eth/src/claims-manager/claimsManager.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,11 @@
import type { PublicClient } from 'viem'

import { abi } from './abi'
import { CLAIMS_MANAGER_CONTRACT_ADDRESS } from './constants'

export class ClaimsManager {
client: PublicClient
address: `0x${string}`

constructor(
client: PublicClient,
{ address }: { address?: `0x${string}` } = {}
) {
this.client = client
this.address = address ?? CLAIMS_MANAGER_CONTRACT_ADDRESS
}

// Get the duration of a funding round in blocks
getFundingRoundBlockDiff = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getFundingRoundBlockDiff'
})

// Get the last block where a funding round was initiated
getLastFundedBlock = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getLastFundedBlock'
})

// Get the amount funded per round in wei
getFundsPerRound = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getFundsPerRound'
})

// total amount claimed in the current round
getTotalClaimedInRound = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getTotalClaimedInRound'
})

// Get the Governance address
getGovernanceAddress = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getGovernanceAddress'
})

// Get the ServiceProviderFactory address
getServiceProviderFactoryAddress = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getServiceProviderFactoryAddress'
})

// Get the DelegateManager address
getDelegateManagerAddress = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getDelegateManagerAddress'
})

// Get the Staking address
getStakingAddress = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getStakingAddress'
})

claimPending = ({ address }: { address: `0x${string}` }) =>
this.client.readContract({
address: this.address,
abi,
functionName: 'claimPending',
args: [address]
})
/**
* Manages periodic minting and distribution of AUDIO staking rewards.
* Controls funding rounds (~weekly), mints new tokens according to the
* protocol's inflation schedule, and tracks per-round claim amounts.
*/
export const ClaimsManager = {
abi,
address: '0x44617F9dCEd9787C3B06a05B35B4C779a2AA1334' as const
}
2 changes: 0 additions & 2 deletions packages/eth/src/claims-manager/constants.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/eth/src/claims-manager/index.ts

This file was deleted.

13 changes: 9 additions & 4 deletions packages/eth/src/delegate-manager/delegateManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { abi } from './abi'

export class DelegateManager {
public static readonly abi = abi

public static readonly address = '0x4d7968ebfD390D5E7926Cb3587C39eFf2F9FB225'
/**
* Manages delegation of AUDIO tokens to service providers. Delegators can
* increase or decrease their delegated stake with lockup periods to prevent
* anticipatory withdrawal before slashing. Includes per-SP minimum
* delegation amounts (V2).
*/
export const DelegateManager = {
abi,
address: '0x4d7968ebfD390D5E7926Cb3587C39eFf2F9FB225' as const
}
1 change: 0 additions & 1 deletion packages/eth/src/delegate-manager/index.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/eth/src/eth-rewards-manager/constants.ts

This file was deleted.

29 changes: 8 additions & 21 deletions packages/eth/src/eth-rewards-manager/ethRewardsManager.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import type { PublicClient } from 'viem'

import { abi } from './abi'
import { ETH_REWARDS_MANAGER_CONTRACT_ADDRESS } from './constants'

export class EthRewardsManager {
client: PublicClient
address: `0x${string}`

constructor(
client: PublicClient,
{ address }: { address?: `0x${string}` } = {}
) {
this.client = client
this.address = address ?? ETH_REWARDS_MANAGER_CONTRACT_ADDRESS
}

getAntiAbuseOracleAddresses = () =>
this.client.readContract({
address: this.address,
abi,
functionName: 'getAntiAbuseOracleAddresses'
})
/**
* Manages transferring AUDIO reward tokens from Ethereum to Solana via the
* Wormhole bridge for the Solana-based rewards system. Holds anti-abuse
* oracle addresses. Only governance can modify configuration.
*/
export const EthRewardsManager = {
abi,
address: '0x5aa6B99A2B461bA8E97207740f0A689C5C39C3b0' as const
}
2 changes: 0 additions & 2 deletions packages/eth/src/eth-rewards-manager/index.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/eth/src/governance/constants.ts

This file was deleted.

Loading