Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PRE Application to the thershold-ts lib #277

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
7 changes: 7 additions & 0 deletions src/store/account/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ export const getStakingProviderOperatorInfo = async (
})
)

listenerApi.dispatch(
setMappedOperator({
appName: "pre",
operator: mappedOperators.pre,
})
)

listenerApi.dispatch(operatorMappingInitialFetchDone())
} catch (error) {
listenerApi.dispatch(
Expand Down
4 changes: 3 additions & 1 deletion src/store/account/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface AccountState {
mappedOperators: {
tbtc: string
randomBeacon: string
pre: string
}
}>
}
Expand All @@ -33,6 +34,7 @@ export const accountSlice = createSlice({
mappedOperators: {
tbtc: AddressZero,
randomBeacon: AddressZero,
pre: AddressZero,
},
},
isFetching: false,
Expand All @@ -52,7 +54,7 @@ export const accountSlice = createSlice({
setMappedOperator: (
state: AccountState,
action: PayloadAction<{
appName: StakingAppName
appName: StakingAppName | "pre"
operator: string
}>
) => {
Expand Down
2 changes: 2 additions & 0 deletions src/threshold-ts/applications/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,5 @@ export class Application implements IApplication {
return await this._application.operatorToStakingProvider(operator)
}
}

export * from "./preApplication"
118 changes: 118 additions & 0 deletions src/threshold-ts/applications/preApplication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import {
Contract,
BigNumber,
BigNumberish,
ContractTransaction,
ContractInterface,
} from "ethers"
import { AuthorizationParameters, StakingProviderAppInfo } from "."
import { IMulticall } from "../multicall"
import { IStaking } from "../staking"
import { EthereumConfig } from "../types"
import { getContract, isAddressZero } from "../utils"

export interface PREStakingProviderInfo {
/**
* Operator address mapped to a given staking provider
*/
operator: string
/**
* Info if operator is confirmed
*/
operatorConfirmed: boolean
/**
* Timestamp where operator were bonded
*/
operatorStartTimestamp: Number
}

export interface IPREApplication {
/**
* Application address.
*/
address: string

/**
* Application contract.
*/
contract: Contract

/**
* Checks if the operator for the given staking provider is mapped
* @param stakingProvider Staking provider address
* @returns boolean value which informs if operator is mapped for the given
* staking provider
*/
isOperatorMapped(stakingProvider: string): Promise<boolean>

// /**
// * Copied from:
// * https://github.com/nucypher/nucypher/blob/development/nucypher/blockchain/eth/sol/source/contracts/SimplePREApplication.sol#L172-L176
// *
// * Bond operator
// * @param stakingProvider Staking provider address
// * @param operator Operator address. Must be a real address, not a contract
// */
// bondOperator(
// stakingProvider: string,
// operator: string
// ): Promise<ContractTransaction>

// /**
// * Copied from:
// * https://github.com/nucypher/nucypher/blob/development/nucypher/blockchain/eth/sol/source/contracts/SimplePREApplication.sol#L213-L215
// *
// * Make a confirmation by operator
// */
// confirmOperatorAddress(): Promise<ContractTransaction>

/**
* Used to get a registered operator mapped to the given staking provider
* @param stakingProvider Staking provider address
*/
stakingProviderToOperator(stakingProvider: string): Promise<string>

/**
* Used to get staking provider address mapped to the given registered
* operator address
* @param operator Operator address
*/
operatorToStakingProvider(operator: string): Promise<string>
}

export class PREApplication implements IPREApplication {
private _application: Contract
// private _staking: IStaking
private _multicall: IMulticall

constructor(
multicall: IMulticall,
config: EthereumConfig & { address: string; abi: ContractInterface }
) {
const { address, abi, providerOrSigner, account } = config
this._application = getContract(address, abi, providerOrSigner, account)
this._multicall = multicall
}

get address() {
return this._application.address
}
get contract() {
return this._application
}

isOperatorMapped = async (stakingProvider: string): Promise<boolean> => {
const { operator, operatorConfirmed } =
await this._application.stakingProviderInfo(stakingProvider)

return !isAddressZero(operator) && operatorConfirmed
}

stakingProviderToOperator(stakingProvider: string): Promise<string> {
return this._application.getOperatorFromStakingProvider(stakingProvider)
}

operatorToStakingProvider(operator: string): Promise<string> {
return this._application.stakingProviderFromOperator(operator)
}
}
9 changes: 9 additions & 0 deletions src/threshold-ts/mas/__test__/mas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ describe("Multi app staking test", () => {
const mockOperator = "0x4"
const mappedOperatorTbtc = mockOperator
const mappedOperatorRandomBeacon = mockOperator
const mappedOperatorPre = mockOperator

const mulitcallMockResult = [
[mappedOperatorTbtc],
[mappedOperatorRandomBeacon],
[mappedOperatorPre],
]
const spyOnMulticall = jest
.spyOn(multicall, "aggregate")
Expand All @@ -131,10 +133,17 @@ describe("Multi app staking test", () => {
method: "stakingProviderToOperator",
args: [mockStakingProvider],
},
{
interface: mas.pre.contract.interface,
address: mas.pre.address,
method: "getOperatorFromStakingProvider",
args: [mockStakingProvider],
},
])
expect(result).toEqual({
tbtc: mappedOperatorTbtc,
randomBeacon: mappedOperatorRandomBeacon,
pre: mappedOperatorPre,
})
})
})
32 changes: 31 additions & 1 deletion src/threshold-ts/mas/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import RandomBeacon from "@keep-network/random-beacon/artifacts/RandomBeacon.json"
import WalletRegistry from "@keep-network/ecdsa/artifacts/WalletRegistry.json"
import SimplePREApplicationABI from "../utils/abi/SimplePreApplication.json"

import {
Application,
AuthorizationParameters,
IApplication,
IPREApplication,
PREApplication,
} from "../applications"
import { IMulticall, ContractCall } from "../multicall"
import { IStaking } from "../staking"
import { EthereumConfig } from "../types"
import { AddressZero } from "../utils"

export interface SupportedAppAuthorizationParameters {
tbtc: AuthorizationParameters
Expand All @@ -17,19 +22,32 @@ export interface SupportedAppAuthorizationParameters {
export interface MappedOperatorsForStakingProvider {
tbtc: string
randomBeacon: string
pre: string
}

export const PRE_ADDRESSESS = {
1: "0x7E01c9c03FD3737294dbD7630a34845B0F70E5Dd",
5: "0x829fdCDf6Be747FEA37518fBd83dF70EE371fCf2",
1337: AddressZero,
} as Record<number | string, string>

export class MultiAppStaking {
private _staking: IStaking
private _multicall: IMulticall
public readonly randomBeacon: IApplication
public readonly ecdsa: IApplication
public readonly pre: IPREApplication

constructor(
staking: IStaking,
multicall: IMulticall,
config: EthereumConfig
) {
const preAddress = PRE_ADDRESSESS[config.chainId]
if (!preAddress) {
throw new Error("Unsupported chain id")
}

this._staking = staking
this._multicall = multicall
this.randomBeacon = new Application(this._staking, this._multicall, {
Expand All @@ -42,6 +60,11 @@ export class MultiAppStaking {
abi: WalletRegistry.abi,
...config,
})
this.pre = new PREApplication(this._multicall, {
address: preAddress,
abi: SimplePREApplicationABI,
...config,
})
}

async getSupportedAppsAuthParameters(): Promise<SupportedAppAuthorizationParameters> {
Expand Down Expand Up @@ -85,14 +108,21 @@ export class MultiAppStaking {
method: "stakingProviderToOperator",
args: [stakingProvider],
},
{
interface: this.pre.contract.interface,
address: this.pre.address,
method: "getOperatorFromStakingProvider",
args: [stakingProvider],
},
]

const [mappedOperatorTbtc, mappedOperatorRandomBeacon] =
const [mappedOperatorTbtc, mappedOperatorRandomBeacon, mappedOperatorPre] =
await this._multicall.aggregate(calls)

return {
tbtc: mappedOperatorTbtc.toString(),
randomBeacon: mappedOperatorRandomBeacon.toString(),
pre: mappedOperatorPre.toString(),
}
}
}
Loading