Skip to content

Commit

Permalink
feat: implement chainfile (#75)
Browse files Browse the repository at this point in the history
* feat: implement chainfile

* fix lock file

* add read permission

* fix imports
  • Loading branch information
fuxingloh authored Jun 11, 2024
1 parent 2132132 commit e4faf6f
Show file tree
Hide file tree
Showing 32 changed files with 701 additions and 1,263 deletions.
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
- package-ecosystem: npm
directory: '/'
schedule:
interval: 'weekly'
groups:
eslint:
patterns:
- 'eslint'
- '@eslint/*'
33 changes: 0 additions & 33 deletions .github/renovate.json

This file was deleted.

38 changes: 33 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ concurrency:

permissions:
contents: read
packages: read

jobs:
build:
Expand All @@ -30,9 +31,27 @@ jobs:

- run: pnpm turbo run build

test:
name: Test
test_plan:
name: Test [plan]
runs-on: ubuntu-latest
outputs:
packages: ${{ steps.plan.outputs.packages }}
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6

- uses: fuxingloh/turbo-plan@4bd6ef3cdb543fbf5fca55b6b5b74892acecdfa5 # v2
id: plan
with:
task: test

test_run:
name: Test [run]
needs: test_plan
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package: ${{ fromJSON(needs.test_plan.outputs.packages) }}
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6

Expand All @@ -44,10 +63,19 @@ jobs:

- run: pnpm install --frozen-lockfile

# Pre-run build steps, required for the test step
- run: pnpm --filter=solana-container run build:docker
- run: pnpm turbo run test --filter=${{ matrix.package }}

- run: pnpm turbo run test
test_completed:
name: Test [completed]
runs-on: ubuntu-latest
if: always()
needs:
- test_run
steps:
- run: |
if ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'cancelled') }} ; then
exit 1
fi
lint_prettier:
name: Lint [prettier]
Expand Down
11 changes: 1 addition & 10 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,5 @@ build
*.tgz
coverage
.nyc_output

# tsconfig.json
packages/*/**/*.d.ts
packages/*/**/*.d.ts.map
packages/*/**/*.js

# turborepo
.turbo

# contented
.contented
.chainfile
5 changes: 2 additions & 3 deletions .idea/solana-container.iml → .idea/chainfile-solana.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 44 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,60 @@
# Solana Container
# Chainfile Solana

```typescript
import { SolanaContainer, StartedSolanaContainer } from 'solana-testcontainers';
import { Connection, PublicKey } from '@solana/web3.js';
Part of the [Chainfile](https://chainfile.org) ecosystem,
this library provides a Docker image for running `solana-test-validator` in a container for toolchain isolation.
This is particularly useful for language-agnostic development and parallelization of systems.

describe('SolanaContainer', () => {
let container: StartedSolanaContainer;
let connection: Connection;
> The default [solanalabs/solana](https://hub.docker.com/r/solanalabs/solana) is an optimized image,
> when used on a host system that does not support AVX, it will fail with the following error:
> `Incompatible CPU detected: missing AVX support. Please build from source on the target.`
beforeAll(async () => {
container = await new SolanaContainer().start();
connection = new Connection(container.getHostRpcEndpoint(), {
commitment: 'processed',
wsEndpoint: container.getHostWsEndpoint(),
});
});
## `solana-testcontainers`

afterAll(async () => {
await container.stop();
});
This is a standalone testcontainers-node package for running `solana-test-validator` in a container for testing
purposes. You don't need to use the Chainfile ecosystem to use this package.

it('should get processed block height', async () => {
const blockHeight = await connection.getBlockHeight('processed');
expect(blockHeight).toBeGreaterThanOrEqual(0);
});
```shell
npm i -D solana-testcontainers @solana/web3.js
```

```typescript
import { afterAll, beforeAll, expect, it } from '@jest/globals';
import { Connection, PublicKey } from '@solana/web3.js';

import { SolanaContainer, StartedSolanaContainer } from './index';

it('should fund address with 5129000000 lamports with confirmation', async () => {
const publicKey = new PublicKey('Emp8JcXpFnCXzdWBC3ChRPtNQHiiQW6kr61wopT3hbNL');
const lamports = 5_129_000_000;
let container: StartedSolanaContainer;
let connection: Connection;

const block = await connection.getLatestBlockhash('processed');
const signature = await connection.requestAirdrop(publicKey, lamports);
await connection.confirmTransaction({ signature, ...block }, 'processed');
beforeAll(async () => {
container = await new SolanaContainer().start();
connection = container.connection;
});

afterAll(async () => {
await container.stop();
});

const balance = await connection.getBalance(publicKey, 'processed');
expect(balance).toStrictEqual(lamports);
it('should get block 0', async () => {
const block = await connection.getBlock(0);
expect(block).toMatchObject({
blockHeight: 0,
blockhash: expect.any(String),
});
});
```

## Motivation
it('should fund address with 5129000000 lamports with confirmation', async () => {
const publicKey = new PublicKey('Emp8JcXpFnCXzdWBC3ChRPtNQHiiQW6kr61wopT3hbNL');
const lamports = 5_129_000_000;

This library creates a Docker image that isolates the toolchain for Solana from the host system.
This is particularly useful for language-agnostic development and parallelization of systems.
const block = await connection.getLatestBlockhash('processed');
const signature = await connection.requestAirdrop(publicKey, lamports);
await connection.confirmTransaction({ signature, ...block }, 'processed');

The default [solanalabs/solana](https://hub.docker.com/r/solanalabs/solana) is an optimized image,
when used on a host system that does not support AVX, it will fail with the following error:
Incompatible CPU detected: missing AVX support.
Please build from source on the target.
const balance = await connection.getBalance(publicKey, 'processed');
expect(balance).toStrictEqual(lamports);
});
```

## License

Expand Down
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@
},
"devDependencies": {
"@jest/globals": "^29.7.0",
"@swc/core": "^1.5.24",
"@swc/jest": "^0.2.36",
"@types/node": "^20.11.30",
"@swc/core": "^1.5.28",
"@swc/jest": "0.2.36",
"@types/node": "^20.14.2",
"@workspace/eslint-config": "workspace:*",
"@workspace/jest-preset": "workspace:*",
"@workspace/prettier-config": "workspace:*",
"@workspace/tsconfig": "workspace:*",
"eslint": "^8.57.0",
"husky": "^9.0.11",
"jest": "29.7.0",
"lint-staged": "^15.2.5",
"prettier": "^3.2.5",
"turbo": "^1.13.3",
"typescript": "5.4.3",
"prettier": "^3.3.2",
"turbo": "^2.0.3",
"typescript": "5.4.5",
"wait-for-expect": "^3.0.2"
},
"packageManager": "[email protected]",
Expand Down
22 changes: 22 additions & 0 deletions packages/chainfile-solana/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "chainfile-solana",
"version": "0.0.0",
"private": false,
"repository": {
"url": "git+https://github.com/vetumorg/chainfile-solana"
},
"license": "MPL-2.0",
"files": [
"*.json"
],
"scripts": {
"lint": "eslint .",
"test": "jest"
},
"jest": {
"preset": "@workspace/jest-preset"
},
"devDependencies": {
"@chainfile/testcontainers": "^0.5.0"
}
}
38 changes: 38 additions & 0 deletions packages/chainfile-solana/test-validator.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "https://chainfile.org/schema.json",
"caip2": "solana:00000000000000000000000000000000",
"name": "Solana Test Validator",
"values": {
"version": "1.18.15"
},
"containers": {
"solana": {
"image": "ghcr.io/vetumorg/solana-test-validator",
"tag": {
"$value": "version"
},
"source": "https://github.com/vetumorg/chainfile-solana",
"resources": {
"cpu": 0.25,
"memory": 256
},
"endpoints": {
"rpc": {
"port": 8899,
"protocol": "HTTP JSON-RPC 2.0",
"probes": {
"readiness": {
"params": [],
"method": "getBlockHeight",
"match": {
"result": {
"type": "number"
}
}
}
}
}
}
}
}
}
27 changes: 27 additions & 0 deletions packages/chainfile-solana/test-validator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ChainfileTestcontainers } from '@chainfile/testcontainers';
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';

import test from './test-validator.json';

const testcontainers = new ChainfileTestcontainers(test);

beforeAll(async () => {
await testcontainers.start();
});

afterAll(async () => {
await testcontainers.stop();
});

describe('solana', () => {
it('should rpc(getBlockHeight)', async () => {
const response = await testcontainers.get('solana').rpc({
method: 'getBlockHeight',
});

expect(response.status).toStrictEqual(200);
expect(await response.json()).toMatchObject({
result: 0,
});
});
});
Loading

0 comments on commit e4faf6f

Please sign in to comment.