Skip to content

Commit

Permalink
Merge pull request #1978 from aeternity/release/13.3.2
Browse files Browse the repository at this point in the history
Release v13.3.2
  • Loading branch information
davidyuk committed Apr 22, 2024
2 parents 4f06d95 + d2d9642 commit a6f7b75
Show file tree
Hide file tree
Showing 22 changed files with 121 additions and 74 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ jobs:
runs-on: ubuntu-22.04
steps:
- run: |
wget -q https://packages.erlang-solutions.com/erlang/debian/pool/esl-erlang_25.0.4-1~ubuntu~jammy_amd64.deb
sudo apt install --allow-downgrades ./esl-erlang_25.0.4-1~ubuntu~jammy_amd64.deb
wget -q https://packages.erlang-solutions.com/erlang/debian/pool/esl-erlang_25.2.3-1~ubuntu~jammy_amd64.deb
sudo apt install ./esl-erlang_25.2.3-1~ubuntu~jammy_amd64.deb
- uses: actions/checkout@v4
with:
fetch-depth: 100
Expand All @@ -30,8 +30,6 @@ jobs:
BASE: ${{ github.event.pull_request.base.sha }}
run: npx commitlint --from $BASE --to $HEAD --verbose
- run: npm run lint
# TODO: remove after merging https://github.com/aeternity/aeternity/pull/4319
- run: chmod 666 ./docker/accounts-pub.json
- run: docker compose up -d --wait
- run: npx nyc npm test
- run: npx nyc report --reporter=text-lcov > coverage.lcov
Expand Down
5 changes: 1 addition & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ services:
interval: 2s
volumes:
- ./docker/aeternity.yaml:/home/aeternity/node/aeternity.yaml
- ./docker/accounts.json:/home/aeternity/node/data/aeplugin_dev_mode/devmode_prefunded_accounts.json
# TODO: remove after merging https://github.com/aeternity/aeternity/pull/4319
- ./docker/accounts-pub.json:/home/aeternity/node/data/aeplugin_dev_mode/devmode_prefunded_accounts-PUB.json
stop_grace_period: 0s

emitter:
Expand All @@ -22,7 +19,7 @@ services:
condition: service_healthy

compiler:
image: aeternity/aesophia_http:v8.0.0-rc1
image: aeternity/aesophia_http:v8.0.0
ports: [3080:3080]
# TODO: remove after releasing https://github.com/aeternity/aesophia_http/pull/133
healthcheck:
Expand Down
1 change: 0 additions & 1 deletion docker/accounts-pub.json

This file was deleted.

6 changes: 0 additions & 6 deletions docker/accounts.json

This file was deleted.

2 changes: 2 additions & 0 deletions docker/aeternity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ chain:
hard_forks:
"1": 0
"6": 1
genesis_accounts:
ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E: 10000000000000000000000
8 changes: 8 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [13.3.2](https://github.com/aeternity/aepp-sdk-js/compare/v13.3.1...v13.3.2) (2024-04-22)


### Bug Fixes

* **contract:** detect if ACI doesn't match called contract ([8c4287f](https://github.com/aeternity/aepp-sdk-js/commit/8c4287f2cdd1690ed2e07410a322659e4f17f2d3))
* ttl validation error in dev mode by reducing polling intervals ([6f8cdc9](https://github.com/aeternity/aepp-sdk-js/commit/6f8cdc9dd82a7dd7f146739d472dc07018f8d230))

### [13.3.1](https://github.com/aeternity/aepp-sdk-js/compare/v13.3.0...v13.3.1) (2024-04-19)


Expand Down
10 changes: 5 additions & 5 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aeternity/aepp-sdk",
"version": "13.3.1",
"version": "13.3.2",
"description": "SDK for the æternity blockchain",
"main": "dist/aepp-sdk.js",
"types": "es/index.d.ts",
Expand Down Expand Up @@ -111,7 +111,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/aeternity/aepp-sdk-js"
"url": "git+https://github.com/aeternity/aepp-sdk-js.git"
},
"devDependencies": {
"@babel/cli": "^7.23.9",
Expand Down
46 changes: 28 additions & 18 deletions src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,25 @@ import {
* @param type - Type
* @param options - Options
*/
export function _getPollInterval(
type: 'block' | 'microblock', // TODO: rename to 'key-block' | 'micro-block'
{ _expectedMineRate = 180000, _microBlockCycle = 3000 }:
{ _expectedMineRate?: number; _microBlockCycle?: number },
): number {
const base = {
block: _expectedMineRate,
microblock: _microBlockCycle,
}[type];
export async function _getPollInterval(
type: 'key-block' | 'micro-block',
{ _expectedMineRate, _microBlockCycle, onNode }:
{ _expectedMineRate?: number; _microBlockCycle?: number; onNode: Node },
): Promise<number> {
const getVal = async (
t: string,
val: number | undefined,
devModeDef: number,
def: number,
): Promise<number | null> => {
if (t !== type) return null;
if (val != null) return val;
return await onNode?.getNetworkId() === 'ae_dev' ? devModeDef : def;
};

const base = await getVal('key-block', _expectedMineRate, 0, 180000)
?? await getVal('micro-block', _microBlockCycle, 0, 3000)
?? (() => { throw new InternalError(`Unknown type: ${type}`); })();
return Math.floor(base / 3);
}

Expand All @@ -53,7 +63,7 @@ export async function getHeight(
const onNode = unwrapProxy(options.onNode);
if (cached) {
const cache = heightCache.get(onNode);
if (cache != null && cache.time > Date.now() - _getPollInterval('block', options)) {
if (cache != null && cache.time > Date.now() - await _getPollInterval('key-block', options)) {
return cache.height;
}
}
Expand All @@ -77,21 +87,21 @@ export async function getHeight(
export async function poll(
th: Encoded.TxHash,
{
blocks = 5, interval, onNode, ...options
blocks = 5, interval, ...options
}:
{ blocks?: number; interval?: number; onNode: Node } & Parameters<typeof _getPollInterval>[1],
): Promise<TransformNodeType<SignedTx>> {
interval ??= _getPollInterval('microblock', options);
interval ??= await _getPollInterval('micro-block', options);
let max;
do {
const tx = await onNode.getTransactionByHash(th);
const tx = await options.onNode.getTransactionByHash(th);
if (tx.blockHeight !== -1) return tx;
if (max == null) {
max = tx.tx.ttl !== 0 ? -1
: await getHeight({ ...options, onNode, cached: true }) + blocks;
: await getHeight({ ...options, cached: true }) + blocks;
}
await pause(interval);
} while (max === -1 ? true : await getHeight({ ...options, onNode, cached: true }) < max);
} while (max === -1 ? true : await getHeight({ ...options, cached: true }) < max);
throw new TxTimedOutError(blocks, th);
}

Expand All @@ -106,14 +116,14 @@ export async function poll(
*/
export async function awaitHeight(
height: number,
{ interval, onNode, ...options }:
{ interval, ...options }:
{ interval?: number; onNode: Node } & Parameters<typeof _getPollInterval>[1],
): Promise<number> {
interval ??= Math.min(_getPollInterval('block', options), 5000);
interval ??= Math.min(await _getPollInterval('key-block', options), 5000);
let currentHeight;
do {
if (currentHeight != null) await pause(interval);
currentHeight = await getHeight({ onNode });
currentHeight = await getHeight(options);
} while (currentHeight < height);
return currentHeight;
}
Expand Down
3 changes: 3 additions & 0 deletions src/contract/Contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ class Contract<M extends ContractMethodsBase> {
break;
case 'error':
message = decode(returnValue).toString();
if (/Expected \d+ arguments, got \d+/.test(message)) {
throw new ContractError(`ACI doesn't match called contract. Error provided by node: ${message}`);
}
break;
default:
throw new InternalError(`Unknown return type: ${returnType}`);
Expand Down
14 changes: 7 additions & 7 deletions src/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ type OracleQueries = Awaited<ReturnType<Node['getOracleQueriesByPubkey']>>['orac
export function pollForQueries(
oracleId: Encoded.OracleAddress,
onQuery: (query: OracleQueries[number]) => void,
{ interval, onNode, ...options }: { interval?: number; onNode: Node }
{ interval, ...options }: { interval?: number; onNode: Node }
& Parameters<typeof _getPollInterval>[1],
): () => void {
interval ??= _getPollInterval('microblock', options);
const knownQueryIds = new Set();
const checkNewQueries = async (): Promise<void> => {
const queries = ((await onNode.getOracleQueriesByPubkey(oracleId)).oracleQueries ?? [])
const queries = ((await options.onNode.getOracleQueriesByPubkey(oracleId)).oracleQueries ?? [])
.filter(({ id }) => !knownQueryIds.has(id));
queries.forEach((query) => {
knownQueryIds.add(query.id);
Expand All @@ -52,6 +51,7 @@ export function pollForQueries(

// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
interval ??= await _getPollInterval('micro-block', options);
while (!stopped) { // eslint-disable-line no-unmodified-loop-condition
// TODO: allow to handle this error somehow
await checkNewQueries().catch(console.error);
Expand All @@ -74,19 +74,19 @@ export function pollForQueries(
export async function pollForQueryResponse(
oracleId: Encoded.OracleAddress,
queryId: Encoded.OracleQueryId,
{ interval, onNode, ...options }:
{ interval, ...options }:
{ interval?: number; onNode: Node } & Parameters<typeof _getPollInterval>[1],
): Promise<string> {
interval ??= _getPollInterval('microblock', options);
interval ??= await _getPollInterval('micro-block', options);
let height;
let ttl;
let response;
do {
({ response, ttl } = await onNode.getOracleQueryByPubkeyAndQueryId(oracleId, queryId));
({ response, ttl } = await options.onNode.getOracleQueryByPubkeyAndQueryId(oracleId, queryId));
const responseBuffer = decode(response as Encoded.OracleResponse);
if (responseBuffer.length > 0) return responseBuffer.toString();
await pause(interval);
height = await getHeight({ ...options, onNode, cached: true });
height = await getHeight({ ...options, cached: true });
} while (ttl >= height);
throw new RequestTimedOutError(height);
}
Expand Down
5 changes: 1 addition & 4 deletions src/tx/builder/field-types/gas-price.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ export async function getCachedIncreasedGasPrice(node: Node): Promise<bigint> {

// TODO: remove after requiring node@6.13.0
const { nodeVersion } = await node._getCachedStatus();
// TODO: remove remove '6.12.0+' check after releasing 6.13.0
if (!nodeVersion.startsWith('6.12.0+') && !semverSatisfies(nodeVersion, '6.13.0', '8.0.0')) {
return 0n;
}
if (!semverSatisfies(nodeVersion, '6.13.0')) return 0n;

const { minGasPrice, utilization } = (await node.getRecentGasPrices())[0];
let gasPrice = utilization < 70 ? 0n : BigInt(
Expand Down
2 changes: 1 addition & 1 deletion src/tx/builder/field-types/ttl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default {
onNode?: Node;
absoluteTtl?: boolean;
_isInternalBuild?: boolean;
} & Parameters<typeof _getPollInterval>[1],
} & Omit<Parameters<typeof _getPollInterval>[1], 'onNode'>,
) {
if (absoluteTtl !== true && value !== 0 && (value != null || _isInternalBuild === true)) {
if (onNode == null) throw new ArgumentError('onNode', 'provided', onNode);
Expand Down
27 changes: 14 additions & 13 deletions src/utils/semver-satisfies.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
export default function semverSatisfies(
version: string,
geVersion: string,
ltVersion: string,
): boolean {
function verCmp(a: string, b: string): number {
const getComponents = (v: string): number[] => v
.split(/[-+]/)[0].split('.').map((i) => +i);

const versionComponents = getComponents(version);
const geComponents = getComponents(geVersion);
const ltComponents = getComponents(ltVersion);
const aComponents = getComponents(a);
const bComponents = getComponents(b);

const base = Math.max(...versionComponents, ...geComponents, ...ltComponents) + 1;
const base = Math.max(...aComponents, ...bComponents) + 1;
const componentsToNumber = (components: number[]): number => components.reverse()
.reduce((acc, n, idx) => acc + n * base ** idx, 0);

const vNumber = componentsToNumber(versionComponents);
const geNumber = componentsToNumber(geComponents);
const ltNumber = componentsToNumber(ltComponents);
return vNumber >= geNumber && vNumber < ltNumber;
return componentsToNumber(aComponents) - componentsToNumber(bComponents);
}

export default function semverSatisfies(
version: string,
geVersion: string,
ltVersion?: string,
): boolean {
return verCmp(version, geVersion) >= 0
&& (ltVersion == null || verCmp(version, ltVersion) < 0);
}
24 changes: 24 additions & 0 deletions test/integration/AeSdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, it } from 'mocha';
import { expect } from 'chai';
import { getSdk, networkId } from '.';

describe('AeSdk', () => {
describe('_getPollInterval', () => {
it('returns value based on options', async () => {
const aeSdk = await getSdk(0);
aeSdk._options._expectedMineRate = 1000;
aeSdk._options._microBlockCycle = 300;
expect(await aeSdk._getPollInterval('key-block')).to.be.equal(333);
expect(await aeSdk._getPollInterval('micro-block')).to.be.equal(100);
});

it('returns correct value', async () => {
const aeSdk = await getSdk(0);
delete aeSdk._options._expectedMineRate;
delete aeSdk._options._microBlockCycle;
const [kb, mb] = networkId === 'ae_dev' ? [0, 0] : [60000, 1000];
expect(await aeSdk._getPollInterval('key-block')).to.be.equal(kb);
expect(await aeSdk._getPollInterval('micro-block')).to.be.equal(mb);
});
});
});
4 changes: 2 additions & 2 deletions test/integration/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function testCompiler(compiler: CompilerBase, isAesophia7: boolean): void {
let inclFileSystem: Record<string, string>;
const inclBytecode = isAesophia7
? 'cb_+QEGRgOg7BH1sCv+p2IrS0Pn3/i6AfE8lOGUuC71lLPn6mbUm9PAuNm4cv4AWolkAjcCBwcHFBQAAgD+RNZEHwA3ADcAGg6CPwEDP/5Nt4A5AjcCBwcHDAECDAEABAMRAFqJZP6SiyA2ADcBBwcMAwgMAQAEAxFNt4A5/pSgnxIANwF3BwwBAAQDEarAwob+qsDChgI3AXcHPgQAALhgLwYRAFqJZD0uU3VibGlicmFyeS5zdW0RRNZEHxFpbml0EU23gDkxLkxpYnJhcnkuc3VtEZKLIDYRdGVzdBGUoJ8SJWdldExlbmd0aBGqwMKGOS5TdHJpbmcubGVuZ3Rogi8AhTcuNC4xABzDzFw='
: 'cb_+QEKRgOg7BH1sCv+p2IrS0Pn3/i6AfE8lOGUuC71lLPn6mbUm9PAuNm4cv4AWolkAjcCBwcHFBQAAgD+RNZEHwA3ADcAGg6CPwEDP/5Nt4A5AjcCBwcHDAECDAEABAMRAFqJZP6SiyA2ADcBBwcMAwgMAQAEAxFNt4A5/pSgnxIANwF3BwwBAAQDEarAwob+qsDChgI3AXcHPgQAALhgLwYRAFqJZD0uU3VibGlicmFyeS5zdW0RRNZEHxFpbml0EU23gDkxLkxpYnJhcnkuc3VtEZKLIDYRdGVzdBGUoJ8SJWdldExlbmd0aBGqwMKGOS5TdHJpbmcubGVuZ3Rogi8AiTguMC4wLXJjMQCfQIbH';
: 'cb_+QEGRgOg7BH1sCv+p2IrS0Pn3/i6AfE8lOGUuC71lLPn6mbUm9PAuNm4cv4AWolkAjcCBwcHFBQAAgD+RNZEHwA3ADcAGg6CPwEDP/5Nt4A5AjcCBwcHDAECDAEABAMRAFqJZP6SiyA2ADcBBwcMAwgMAQAEAxFNt4A5/pSgnxIANwF3BwwBAAQDEarAwob+qsDChgI3AXcHPgQAALhgLwYRAFqJZD0uU3VibGlicmFyeS5zdW0RRNZEHxFpbml0EU23gDkxLkxpYnJhcnkuc3VtEZKLIDYRdGVzdBGUoJ8SJWdldExlbmd0aBGqwMKGOS5TdHJpbmcubGVuZ3Rogi8AhTguMC4wAIUiDfs=';
const testBytecode = 'cb_+GhGA6BgYgXqYB9ctBcQ8mJ0+we5OXhb9PpsSQWP2DhPx9obn8C4O57+RNZEHwA3ADcAGg6CPwEDP/6AeCCSADcBd3cBAQCYLwIRRNZEHxFpbml0EYB4IJIZZ2V0QXJngi8AhTcuMC4xAMXqWXc=';

const interfaceSourceCodePath = './test/integration/contracts/Interface.aes';
Expand Down Expand Up @@ -63,7 +63,7 @@ function testCompiler(compiler: CompilerBase, isAesophia7: boolean): void {
});

it('returns version', async () => {
expect(await compiler.version()).to.be.equal(isAesophia7 ? '7.4.1' : '8.0.0-rc1');
expect(await compiler.version()).to.be.equal(isAesophia7 ? '7.4.1' : '8.0.0');
});

it('compiles and generates aci by path', async () => {
Expand Down
13 changes: 13 additions & 0 deletions test/integration/contract-aci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
NoSuchContractFunctionError,
ConsensusProtocolVersion,
InvalidTxError,
ContractError,
} from '../../src';
import { getSdk } from '.';
import {
Expand Down Expand Up @@ -362,6 +363,18 @@ describe('Contract instance', () => {
expect((await contract.intFn(3)).decodedResult).to.be.equal(3n);
});

it('fails if aci doesn\'t match called contract', async () => {
const aci = structuredClone(testContractAci);
const fn = aci.at(-1)?.contract?.functions.find(({ name }) => name === 'intFn');
assertNotNull(fn);
fn.arguments.push(fn.arguments[0]);
const contract = await aeSdk.initializeContract<{
intFn: (a: InputNumber, b: InputNumber) => bigint;
}>({ aci, address: testContract.$options.address });
await expect(contract.intFn(3, 2)).to.be
.rejectedWith(ContractError, 'ACI doesn\'t match called contract. Error provided by node: Expected 1 arguments, got 2');
});

it('deploys and calls by bytecode and aci', async () => {
const contract = await aeSdk.initializeContract<TestContractApi>(
{ bytecode: testContractBytecode, aci: testContractAci },
Expand Down
2 changes: 1 addition & 1 deletion test/integration/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe('Transaction', () => {
if (consensusProtocolVersion === ConsensusProtocolVersion.Iris) {
return 'tx_+LAqAaEBhAyXS5cWR3ZFS6EZ2E7cTWBYqN7JK27cV4qy0wtMQgABuGr4aEYDoKEijZbj/w2AeiWwAbldusME5pm3ZgPuomnZ3TbUbYgrwLg7nv5E1kQfADcANwAaDoI/AQM//oB4IJIANwEHBwEBAJgvAhFE1kQfEWluaXQRgHggkhlnZXRBcmeCLwCFNy40LjEAgwcAA4ZHcyzkwAAAAACDTEtAhDuaygCHKxFE1kQfP+mk9Ac=';
}
return 'tx_+LQqAaEBhAyXS5cWR3ZFS6EZ2E7cTWBYqN7JK27cV4qy0wtMQgABuG74bEYDoKEijZbj/w2AeiWwAbldusME5pm3ZgPuomnZ3TbUbYgrwLg7nv5E1kQfADcANwAaDoI/AQM//oB4IJIANwEHBwEBAJgvAhFE1kQfEWluaXQRgHggkhlnZXRBcmeCLwCJOC4wLjAtcmMxAIMIAAOGR4XNQ+AAAAAAg0xLQIQ7msoAhysRRNZEHz+l4Zcy';
return 'tx_+LAqAaEBhAyXS5cWR3ZFS6EZ2E7cTWBYqN7JK27cV4qy0wtMQgABuGr4aEYDoKEijZbj/w2AeiWwAbldusME5pm3ZgPuomnZ3TbUbYgrwLg7nv5E1kQfADcANwAaDoI/AQM//oB4IJIANwEHBwEBAJgvAhFE1kQfEWluaXQRgHggkhlnZXRBcmeCLwCFOC4wLjAAgwgAA4ZHcyzkwAAAAACDTEtAhDuaygCHKxFE1kQfP6UPXo4=';
},
async () => aeSdk.buildTx({
tag: Tag.ContractCreateTx,
Expand Down
Loading

0 comments on commit a6f7b75

Please sign in to comment.