Skip to content

Commit

Permalink
feat: add a list of staking contracts
Browse files Browse the repository at this point in the history
Signed-off-by: Raymond Feng <[email protected]>
  • Loading branch information
raymondfeng committed Aug 12, 2022
1 parent 2763179 commit 9b0f315
Show file tree
Hide file tree
Showing 15 changed files with 365 additions and 45 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules/
dist/
coverage/
.eslintrc.js
src/types/
hardhat.config.js
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dist
src/types
119 changes: 118 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,120 @@
# collabland@/staking-contracts
# @collabland/staking-contracts

This project provides support for a curated list of stacking contracts for Collab.Land's token gating capabilities.

## Get started

1. Install dependencies

```sh
npm install
```

2. Run the build

```sh
npm run build
```

3. Run the example

```sh
node dist/__examples__/main
```

## Format code and check style

```sh
npm run lint
```

or

```sh
npm run lint:fix
```

## Add a new staking contract

To add a new staking contract, please follow the steps below.

1. Add the contract ABI json file, go to `src/contracts` and create a file such
as `my-abi.json`

2. Run `npm run build` to generate TypeScript client code for the contract

3. Add an adapter class to `src/adapters`:

```ts
import {Provider} from '@ethersproject/abstract-provider';
import {BindingScope, extensionFor, injectable} from '@loopback/core';
import {BigNumber} from 'ethers';
import {STAKING_ADAPTERS_EXTENSION_POINT} from '../keys';
import {StackingContractAdapter} from '../staking';
// Use the full path to import instead of `../types`
import {Coco__factory} from '../types/factories/Coco__factory';

@injectable(
{
scope: BindingScope.SINGLETON, // Mark the adapter as a singleton
},
// Mark it as an extension to staking contracts service
extensionFor(STAKING_ADAPTERS_EXTENSION_POINT),
)
export class CocoStakingContractAdapter implements StackingContractAdapter {
/**
* The contract address
*/
contractAddress = '0x0Df016Fb18ef4195b2CF9d8623E236272ec52e14';

/**
* Get staked token ids for the given owner
* @param provider - Ethers provider
* @param owner - Owner address
* @returns
*/
getStakedTokenIds(provider: Provider, owner: string): Promise<BigNumber[]> {
const contract = Coco__factory.connect(this.contractAddress, provider);
return contract.getStakes(owner);
}
}
```

4. Register the adapter class to `src/component.ts`

```ts
// Copyright Abridged, Inc. 2022. All Rights Reserved.
// Node module: @collabland/staking-contracts
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {
Component,
ContextTags,
injectable,
ServiceOrProviderClass,
} from '@loopback/core';
import {CocoStakingContractAdapter} from './adapters/coco.adapter';
import {MtgStakingContractAdapter} from './adapters/mtg.adapter';
import {RirsuStakingContractAdapter} from './adapters/rirsu.adapter';
import {RoboStakingContractAdapter} from './adapters/robo.adapter';
import {SkyFarmContractAdapter} from './adapters/sky-farm.adapter';
import {STAKING_CONTRACTS_COMPONENT} from './keys';
import {StakingContractsService} from './services/staking-contracts.service';

// Configure the binding for StakingContractsComponent
@injectable({
tags: {[ContextTags.KEY]: STAKING_CONTRACTS_COMPONENT},
})
export class StakingContractsComponent implements Component {
services: ServiceOrProviderClass<unknown>[] = [
StakingContractsService,
CocoStakingContractAdapter,
MtgStakingContractAdapter,
RirsuStakingContractAdapter,
RoboStakingContractAdapter,
SkyFarmContractAdapter,
];
constructor() {}
}
```
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"README.md",
"dist",
"src",
"!*/__tests__"
"!*/__tests__",
"!*/__examples__"
],
"peerDependencies": {
"@loopback/core": "^4.0.2"
Expand Down
25 changes: 25 additions & 0 deletions src/__examples__/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {Application} from '@loopback/core';
import {getDefaultProvider} from 'ethers';
import {StakingContractsComponent} from '../component';
import {STAKING_CONTRACTS_SERVICE} from '../keys';

async function main() {
const app = new Application();
app.component(StakingContractsComponent);
const service = await app.get(STAKING_CONTRACTS_SERVICE);
const provider = getDefaultProvider(1);
const staked = await service.getStakedTokenIds(
provider,
'0x9abbf7218c65c4d22c8483b5d6be93075a3c159c',
);
console.log(staked);
await app.stop();
process.exit(0);
}

if (require.main === module) {
main().catch(err => {
console.error(err);
process.exit(1);
});
}
32 changes: 32 additions & 0 deletions src/adapters/coco.adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {Provider} from '@ethersproject/abstract-provider';
import {BindingScope, extensionFor, injectable} from '@loopback/core';
import {BigNumber} from 'ethers';
import {STAKING_ADAPTERS_EXTENSION_POINT} from '../keys';
import {StackingContractAdapter} from '../staking';
// Use the full path to import instead of `../types`
import {Coco__factory} from '../types/factories/Coco__factory';

@injectable(
{
scope: BindingScope.SINGLETON, // Mark the adapter as a singleton
},
// Mark it as an extension to staking contracts service
extensionFor(STAKING_ADAPTERS_EXTENSION_POINT),
)
export class CocoStakingContractAdapter implements StackingContractAdapter {
/**
* The contract address
*/
contractAddress = '0x0Df016Fb18ef4195b2CF9d8623E236272ec52e14';

/**
* Get staked token ids for the given owner
* @param provider - Ethers provider
* @param owner - Owner address
* @returns
*/
getStakedTokenIds(provider: Provider, owner: string): Promise<BigNumber[]> {
const contract = Coco__factory.connect(this.contractAddress, provider);
return contract.getStakes(owner);
}
}
28 changes: 28 additions & 0 deletions src/adapters/mtg.adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {Provider} from '@ethersproject/abstract-provider';
import {BindingScope, extensionFor, injectable} from '@loopback/core';
import {BigNumber} from 'ethers';
import {STAKING_ADAPTERS_EXTENSION_POINT} from '../keys';
import {StackingContractAdapter} from '../staking';
import {MtgStaking__factory} from '../types/factories/MtgStaking__factory';

@injectable(
{
scope: BindingScope.SINGLETON,
},
extensionFor(STAKING_ADAPTERS_EXTENSION_POINT),
)
export class MtgStakingContractAdapter implements StackingContractAdapter {
contractAddress = '0x2eb255a465c828837d6e8ba73072ec2c965dcf13';

async getStakedTokenIds(
provider: Provider,
owner: string,
): Promise<BigNumber[]> {
const contract = MtgStaking__factory.connect(
this.contractAddress,
provider,
);
const records = await contract.getStakingRecords(owner);
return records[0];
}
}
24 changes: 24 additions & 0 deletions src/adapters/rirsu.adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {Provider} from '@ethersproject/abstract-provider';
import {BindingScope, extensionFor, injectable} from '@loopback/core';
import {BigNumber} from 'ethers';
import {STAKING_ADAPTERS_EXTENSION_POINT} from '../keys';
import {StackingContractAdapter} from '../staking';
import {RirsuStaking__factory} from '../types/factories/RirsuStaking__factory';

@injectable(
{
scope: BindingScope.SINGLETON,
},
extensionFor(STAKING_ADAPTERS_EXTENSION_POINT),
)
export class RirsuStakingContractAdapter implements StackingContractAdapter {
contractAddress = '0x5dACC3a466fD9E39DCCB2fabE0852285a76a2c59';

getStakedTokenIds(provider: Provider, owner: string): Promise<BigNumber[]> {
const contract = RirsuStaking__factory.connect(
this.contractAddress,
provider,
);
return contract.stakedRiris(owner);
}
}
24 changes: 24 additions & 0 deletions src/adapters/robo.adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {Provider} from '@ethersproject/abstract-provider';
import {BindingScope, extensionFor, injectable} from '@loopback/core';
import {BigNumber} from 'ethers';
import {STAKING_ADAPTERS_EXTENSION_POINT} from '../keys';
import {StackingContractAdapter} from '../staking';
import {RoboStaking__factory} from '../types/factories/RoboStaking__factory';

@injectable(
{
scope: BindingScope.SINGLETON,
},
extensionFor(STAKING_ADAPTERS_EXTENSION_POINT),
)
export class RoboStakingContractAdapter implements StackingContractAdapter {
contractAddress = '0x5dACC3a466fD9E39DCCB2fabE0852285a76a2c59';

getStakedTokenIds(provider: Provider, owner: string): Promise<BigNumber[]> {
const contract = RoboStaking__factory.connect(
this.contractAddress,
provider,
);
return contract.getStaked(owner);
}
}
21 changes: 21 additions & 0 deletions src/adapters/sky-farm.adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {Provider} from '@ethersproject/abstract-provider';
import {BindingScope, extensionFor, injectable} from '@loopback/core';
import {BigNumber} from 'ethers';
import {STAKING_ADAPTERS_EXTENSION_POINT} from '../keys';
import {StackingContractAdapter} from '../staking';
import {SkyFarm__factory} from '../types/factories/SkyFarm__factory';

@injectable(
{
scope: BindingScope.SINGLETON,
},
extensionFor(STAKING_ADAPTERS_EXTENSION_POINT),
)
export class SkyFarmContractAdapter implements StackingContractAdapter {
contractAddress = '0xc5933172228E273CF829672921290ca107611757';

getStakedTokenIds(provider: Provider, owner: string): Promise<BigNumber[]> {
const contract = SkyFarm__factory.connect(this.contractAddress, provider);
return contract.getStakedIds(owner);
}
}
36 changes: 19 additions & 17 deletions src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,31 @@
// License text available at https://opensource.org/licenses/MIT

import {
Application,
injectable,
Component,
config,
ContextTags,
CoreBindings,
inject,
injectable,
ServiceOrProviderClass,
} from '@loopback/core';
import {StakingContractsComponentBindings} from './keys';
import {
DEFAULT_COLLABLAND_STAKING_OPTIONS,
StakingContractsComponentOptions,
} from './types';
import {CocoStakingContractAdapter} from './adapters/coco.adapter';
import {MtgStakingContractAdapter} from './adapters/mtg.adapter';
import {RirsuStakingContractAdapter} from './adapters/rirsu.adapter';
import {RoboStakingContractAdapter} from './adapters/robo.adapter';
import {SkyFarmContractAdapter} from './adapters/sky-farm.adapter';
import {STAKING_CONTRACTS_COMPONENT} from './keys';
import {StakingContractsService} from './services/staking-contracts.service';

// Configure the binding for StakingContractsComponent
@injectable({
tags: {[ContextTags.KEY]: StakingContractsComponentBindings.COMPONENT},
tags: {[ContextTags.KEY]: STAKING_CONTRACTS_COMPONENT},
})
export class StakingContractsComponent implements Component {
constructor(
@inject(CoreBindings.APPLICATION_INSTANCE)
private application: Application,
@config()
private options: StakingContractsComponentOptions = DEFAULT_COLLABLAND_STAKING_OPTIONS,
) {}
services: ServiceOrProviderClass<unknown>[] = [
StakingContractsService,
CocoStakingContractAdapter,
MtgStakingContractAdapter,
RirsuStakingContractAdapter,
RoboStakingContractAdapter,
SkyFarmContractAdapter,
];
constructor() {}
}
18 changes: 11 additions & 7 deletions src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
// License text available at https://opensource.org/licenses/MIT

import {BindingKey, CoreBindings} from '@loopback/core';
import {StakingContractsComponent} from './component';
import type {StakingContractsComponent} from './component';
import type {StakingContractsService} from './services/staking-contracts.service';

/**
* Binding keys used by this component.
*/
export namespace StakingContractsComponentBindings {
export const COMPONENT = BindingKey.create<StakingContractsComponent>(
export const STAKING_CONTRACTS_COMPONENT =
BindingKey.create<StakingContractsComponent>(
`${CoreBindings.COMPONENTS}.StakingContractsComponent`,
);
}

export const STAKING_CONTRACTS_SERVICE =
BindingKey.create<StakingContractsService>(
'services.StakingContractsService',
);

export const STAKING_ADAPTERS_EXTENSION_POINT = 'collabland.stakingContracts';
Loading

0 comments on commit 9b0f315

Please sign in to comment.