Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/react-declarative/erc20-payment-gateway
Payment gateway for ERC-20 (USDT-like) tokens
https://github.com/react-declarative/erc20-payment-gateway
dependency-injection erc20 ethereum evm functional-programming mobx mui object-oriented-programming openzeppelin payment-gateway react smart-contracts solid solidity typescript
Last synced: about 1 month ago
JSON representation
Payment gateway for ERC-20 (USDT-like) tokens
- Host: GitHub
- URL: https://github.com/react-declarative/erc20-payment-gateway
- Owner: react-declarative
- License: mit
- Created: 2023-01-07T19:36:09.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2023-04-08T13:08:24.000Z (over 1 year ago)
- Last Synced: 2024-05-04T00:17:51.252Z (8 months ago)
- Topics: dependency-injection, erc20, ethereum, evm, functional-programming, mobx, mui, object-oriented-programming, openzeppelin, payment-gateway, react, smart-contracts, solid, solidity, typescript
- Language: TypeScript
- Homepage:
- Size: 4.17 MB
- Stars: 8
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# erc20-payment-gateway
> A payment gateway for any `IERC20` tokens (USDT) with testbed on top of [TestERC20](https://stackoverflow.com/questions/75043524/minimal-erc20-contract-for-testing/75043525#75043525) token
![screencast.git](./assets/screencast.gif)
## Contribute
> [!IMPORTANT]
> Made by using [react-declarative](https://github.com/react-declarative/react-declarative) to solve your problems. **⭐Star** and **💻Fork** It on github will be appreciated## Usage
1. Run `npm run start:ganache` in separated terminal
2. Run `npm run deploy:contracts` to deploy contracts to ganache
3. Run this DApp by running `npm start` in [client](./packages/client) folder. Send some tokens
4. Check admin menu by typing secret cheat-code `133337`
5. If you need test eth's on a balance check [config.json](./config.json). The smart-contract is going to mint 10_000 tokens for the first address in the list.## Contract source code
> Solidity
```solidity
contract PaymentGatewayContract {IERC20 private erc20;
address public owner;uint256 public deployBlock;
constructor(address _erc20Address) {
erc20 = IERC20(_erc20Address);
owner = msg.sender;
deployBlock = block.number;
}function sendUSDT(uint256 _amount, bytes32 _data) public {
uint256 allowance = erc20.allowance(msg.sender, address(this));require(allowance >= _amount, "ERC20 allowance not sufficient");
bool transferSuccess = erc20.transferFrom(msg.sender, owner, _amount);require(transferSuccess, "Failed to transfer ERC20");
emit Transfer(msg.sender, _amount, _data);
}event Transfer(address indexed sender, uint256 amount, bytes32 _data);
}
```> TypeScript
```tsx
export class ContractService {private readonly ethersService = inject(TYPES.ethersService);
public readonly transferSubject = new Subject<{
sender: string;
amount: number;
data: string;
}>();private _instance: IContract = null as never;
get isContractConnected() {
return !!this._instance;
};constructor() {
makeAutoObservable(this);
};getDeployBlock = async () => Number(await this._instance.deployBlock());
sendUSDT = async (_amount: number, _data: string) => {
const result = await this._instance.sendUSDT(String(_amount), toBytes32(_data));
const rc = await result.wait();
const event = rc.events.find((event: any) => event.event === 'Transfer');
const [sender, amount, data] = event.args;
return {
sender,
amount: Number(amount),
data: fromBytes32(data),
};
};getTransferList = async () => {
const eventSignature = 'Transfer(address,uint256,bytes32)';
const eventTopic = ethers.utils.id(eventSignature);
const deployBlock = await this.getDeployBlock();
const currentBlock = await this.ethersService.provider.getBlockNumber();
const parser = new ethers.utils.Interface(CC_CONTRACT_ABI);
const rawLogs = await this.ethersService.provider.getLogs({
address: CC_CONTRACT_ADDRESS,
topics: [eventTopic],
fromBlock: deployBlock,
toBlock: currentBlock,
});
return rawLogs.map((log, idx) => {
const parsedLog = parser.parseLog(log);
const [sender, amount, data] = parsedLog.args;
return {
id: `${idx}`,
sender,
amount: Number(amount),
data: fromBytes32(data),
};
});
};prefetch = singleshot(async () => {
console.log("ContractService prefetch started");
try {
const deployedCode = await this.ethersService.getCode(CC_CONTRACT_ADDRESS);
if (deployedCode === '0x') {
throw new Error('ContractService contract not deployed');
}
const instance = new ethers.Contract(
CC_CONTRACT_ADDRESS,
CC_CONTRACT_ABI,
this.ethersService.getSigner(),
) as IContract;
runInAction(() => this._instance = instance);
this.ethersService.provider.once("block", () => {
instance.on('Transfer', (sender: string, amount: BigInt, data: string) => {
this.transferSubject.next({
sender,
amount: Number(amount),
data: fromBytes32(data),
});
});
});
} catch (e) {
console.warn('ContractService prefetch failed', e);
}
});};
```