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

feat: implement chainfile #75

Merged
merged 4 commits into from
Jun 11, 2024
Merged
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
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