Skip to content

Commit

Permalink
Merge branch 'master' into aaronmgdr/airtable-upgrade
Browse files Browse the repository at this point in the history
* master:
  [Wallet] Wallet can switch between hosted and local node (#1419)
  [Wallet] Prevent error from Avatar when name is missing (#1454)
  [Wallet] Show splash screen until JS is ready on iOS (#1453)
  Use new segment api keys used by both iOS and Android (#1452)
  [Wallet] Don't log all props, which includes i18n (#1445)
  [Helm] Updated the helm package to deploy the upgraded blockscout version (#1129)
  Tiny copy change (#1429)
  [contractkit] SortedOraclesWrapper + tests (#1405)
  [wallet] Refactor leftover thunk to sagas (#1388)
  [Wallet] Fix repeated QR code scanning and related navigation issues (#1439)
  [Wallet] Show the currency values with correct rounding. (#1435)
  [Wallet] Fix firebase initialization error on iOS after reinstalling the app (#1423)
  [Wallet] Use exit on iOS since we can't restart like Android (#1424)
  [Wallet] Update local currency styles and layout (#1325)
  Reset pincode cache if unlock fails (#1430)
  • Loading branch information
aaronmgdr committed Oct 24, 2019
2 parents a4a38cc + 1c82ae6 commit 9565b53
Show file tree
Hide file tree
Showing 124 changed files with 2,703 additions and 1,270 deletions.
3 changes: 1 addition & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ CLUSTER_DOMAIN_NAME="celo-networks-dev"
TESTNET_PROJECT_NAME="celo-testnet"

BLOCKSCOUT_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/blockscout"
BLOCKSCOUT_WEB_DOCKER_IMAGE_TAG="web-f6c3e0888d1d0ef72dc8bf870808702b7fd13730"
BLOCKSCOUT_INDEXER_DOCKER_IMAGE_TAG="indexer-f6c3e0888d1d0ef72dc8bf870808702b7fd13730"
BLOCKSCOUT_DOCKER_IMAGE_TAG="5fba4843b3e78b5ab75d01766214cb24c6a40649"
BLOCKSCOUT_WEB_REPLICAS=3
BLOCKSCOUT_DB_SUFFIX=

Expand Down
3 changes: 1 addition & 2 deletions .env.integration
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ CLUSTER_DOMAIN_NAME="celo-testnet"
TESTNET_PROJECT_NAME="celo-testnet"

BLOCKSCOUT_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/blockscout"
BLOCKSCOUT_WEB_DOCKER_IMAGE_TAG="web-f6c3e0888d1d0ef72dc8bf870808702b7fd13730"
BLOCKSCOUT_INDEXER_DOCKER_IMAGE_TAG="indexer-f6c3e0888d1d0ef72dc8bf870808702b7fd13730"
BLOCKSCOUT_DOCKER_IMAGE_TAG="ad86714d629c01272e0651dec1fb6a968c3cec71"
BLOCKSCOUT_WEB_REPLICAS=3
BLOCKSCOUT_DB_SUFFIX="25"
BLOCKSCOUT_SUBNETWORK_NAME="Integration"
Expand Down
20 changes: 10 additions & 10 deletions README-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@

Many packages depend on other packages within the monorepo. When this happens, follow these rules:

1. All packages must use **master version** of sibling packages.
2. Exception to (1) are packages that represent a GAE/firebase app which must use the last published version.
3. To differentiate published vs unpublished version. Master version (in package.json) must end with suffix `-dev` and should not be published.
4. If a developer want to publish a version; then after publishing it needs to set master version to next `-dev` version and change all package.json that require on it.
1. All packages must use **master version** of sibling packages.
2. Exception to (1) are packages that represent a GAE/firebase app which must use the last published version.
3. To differentiate published vs unpublished version. Master version (in package.json) must end with suffix `-dev` and should not be published.
4. If a developer want to publish a version; then after publishing it needs to set master version to next `-dev` version and change all package.json that require on it.

To check which pakages need amending, you can run (in the root pkg):

yarn check:packages

A practical example:

* In any given moment, `contractkit/package.json#version` field **must** of the form `x.y.z-dev`
* If current version of contractkit is: `0.1.6-dev` and we want to publish a new version, we should:
* publish version `0.1.6`
* change `package.json#version` to `0.1.7-dev`
* change in other packages within monorepo that were using `0.1.6-dev` to `0.1.7-dev`
- In any given moment, `contractkit/package.json#version` field **must** of the form `x.y.z-dev`
- If current version of contractkit is: `0.1.6-dev` and we want to publish a new version, we should:
- publish version `0.1.6`
- change `package.json#version` to `0.1.7-dev`
- change in other packages within monorepo that were using `0.1.6-dev` to `0.1.7-dev`

## How to publish a new npm package

First checkout the alfajores branch.
Expand Down
3 changes: 1 addition & 2 deletions packages/celotool/src/lib/blockscout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ async function helmParameters(
const params = [
`--set domain.name=${fetchEnv('CLUSTER_DOMAIN_NAME')}`,
`--set blockscout.image.repository=${fetchEnv('BLOCKSCOUT_DOCKER_IMAGE_REPOSITORY')}`,
`--set blockscout.image.webTag=${fetchEnv('BLOCKSCOUT_WEB_DOCKER_IMAGE_TAG')}`,
`--set blockscout.image.indexerTag=${fetchEnv('BLOCKSCOUT_INDEXER_DOCKER_IMAGE_TAG')}`,
`--set blockscout.image.tag=${fetchEnv('BLOCKSCOUT_DOCKER_IMAGE_TAG')}`,
`--set blockscout.db.username=${blockscoutDBUsername}`,
`--set blockscout.db.password=${blockscoutDBPassword}`,
`--set blockscout.db.connection_name=${blockscoutDBConnectionName.trim()}`,
Expand Down
4 changes: 2 additions & 2 deletions packages/celotool/src/lib/helm_deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,10 @@ export async function grantRoles(
export async function retrieveCloudSQLConnectionInfo(celoEnv: string, instanceName: string) {
await validateExistingCloudSQLInstance(instanceName)
const [blockscoutDBUsername] = await execCmdWithExitOnFailure(
`kubectl get secret ${celoEnv}-blockscout --export -o jsonpath='{.data.DB_USERNAME}' -n ${celoEnv} | base64 --decode`
`kubectl get secret ${celoEnv}-blockscout --export -o jsonpath='{.data.DATABASE_USER}' -n ${celoEnv} | base64 --decode`
)
const [blockscoutDBPassword] = await execCmdWithExitOnFailure(
`kubectl get secret ${celoEnv}-blockscout --export -o jsonpath='{.data.DB_PASSWORD}' -n ${celoEnv} | base64 --decode`
`kubectl get secret ${celoEnv}-blockscout --export -o jsonpath='{.data.DATABASE_PASSWORD}' -n ${celoEnv} | base64 --decode`
)
const [blockscoutDBConnectionName] = await execCmdWithExitOnFailure(
`gcloud sql instances describe ${instanceName} --format="value(connectionName)"`
Expand Down
2 changes: 1 addition & 1 deletion packages/contractkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"clean:all": "yarn clean && rm -rf src/generated",
"build:gen": "yarn --cwd ../protocol build",
"prepublishOnly": "yarn build:gen && yarn build",
"test:prepare": "yarn --cwd ../protocol devchain generate .devchain",
"test:prepare": "yarn --cwd ../protocol devchain generate .devchain --migration_override src/test-utils/migration-override.json",
"test": "jest --runInBand",
"lint": "tslint -c tslint.json --project ."
},
Expand Down
7 changes: 7 additions & 0 deletions packages/contractkit/src/test-utils/ganache-test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import * as fs from 'fs'
import Web3 from 'web3'
import { JsonRPCResponse } from 'web3/providers'
import { injectDebugProvider } from '../providers/debug-provider'

// This file specifies accounts available when ganache is running. These are derived
// from the MNEMONIC
export const NetworkConfig = JSON.parse(
fs.readFileSync('src/test-utils/migration-override.json').toString()
)

export function jsonRpcCall<O>(web3: Web3, method: string, params: any[]): Promise<O> {
return new Promise<O>((resolve, reject) => {
web3.currentProvider.send(
Expand Down
11 changes: 11 additions & 0 deletions packages/contractkit/src/test-utils/migration-override.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"stableToken": {
"initialAccounts": [],
"priceOracleAccounts": [
"0x5409ED021D9299bf6814279A6A1411A7e866A631",
"0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84",
"0x06cEf8E666768cC40Cc78CF93d9611019dDcB628",
"0x7457d5E02197480Db681D3fdF256c7acA21bDc12"
]
}
}
240 changes: 240 additions & 0 deletions packages/contractkit/src/wrappers/SortedOracles.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import { Address, CeloContract } from '../base'
import { newKitFromWeb3 } from '../kit'
import { NetworkConfig, testWithGanache } from '../test-utils/ganache-test'
import { OracleRate, SortedOraclesWrapper } from './SortedOracles'

/*
TEST NOTES:
- In migrations: The only account that has cUSD is accounts[0]
*/

testWithGanache('SortedOracles Wrapper', (web3) => {
// NOTE: These values are set in test-utils/network-config.json, and are derived
// from the MNEMONIC. If the MNEMONIC has changed, these will need to be reset.
// To do that, look at the output of web3.eth.getAccounts(), and pick a few
// addresses from that set to be oracles
const stableTokenOracles: Address[] = NetworkConfig.stableToken.priceOracleAccounts
const oracleAddress = stableTokenOracles[stableTokenOracles.length - 1]

const kit = newKitFromWeb3(web3)
let allAccounts: Address[]
let sortedOracles: SortedOraclesWrapper
let stableTokenAddress: Address
let nonOracleAddress: Address

beforeAll(async () => {
sortedOracles = await kit.contracts.getSortedOracles()
stableTokenAddress = await kit.registry.addressFor(CeloContract.StableToken)
allAccounts = await web3.eth.getAccounts()
nonOracleAddress = allAccounts.find((addr) => {
return !stableTokenOracles.includes(addr)
})!
})

describe('#report', () => {
const numerator = 16
const denominator = 1

describe('when reporting from a whitelisted Oracle', () => {
it('should be able to report a rate', async () => {
const initialRates: OracleRate[] = await sortedOracles.getRates(CeloContract.StableToken)

const tx = await sortedOracles.report(
CeloContract.StableToken,
numerator,
denominator,
oracleAddress
)
await tx.sendAndWaitForReceipt()

const resultingRates: OracleRate[] = await sortedOracles.getRates(CeloContract.StableToken)
expect(resultingRates).not.toMatchObject(initialRates)
})

describe('when inserting into the middle of the existing rates', () => {
beforeEach(async () => {
const rates = [15, 20, 17]
for (let i = 0; i < stableTokenOracles.length - 1; i++) {
const tx = await sortedOracles.report(
CeloContract.StableToken,
rates[i],
denominator,
stableTokenOracles[i]
)
await tx.sendAndWaitForReceipt()
}
})

const expectedLesserKey = stableTokenOracles[0]
const expectedGreaterKey = stableTokenOracles[2]

const expectedOracleOrder = [
stableTokenOracles[1],
stableTokenOracles[2],
oracleAddress,
stableTokenOracles[0],
]

it('passes the correct lesserKey and greaterKey as args', async () => {
const tx = await sortedOracles.report(
CeloContract.StableToken,
numerator,
denominator,
oracleAddress
)
const actualArgs = tx.txo.arguments
expect(actualArgs[3]).toEqual(expectedLesserKey)
expect(actualArgs[4]).toEqual(expectedGreaterKey)

await tx.sendAndWaitForReceipt()
})

it('inserts the new record in the right place', async () => {
const tx = await sortedOracles.report(
CeloContract.StableToken,
numerator,
denominator,
oracleAddress
)
await tx.sendAndWaitForReceipt()

const resultingRates: OracleRate[] = await sortedOracles.getRates(
CeloContract.StableToken
)

expect(resultingRates.map((r) => r.address)).toEqual(expectedOracleOrder)
})
})
})

describe('when reporting from a non-oracle address', () => {
it('should raise an error', async () => {
const tx = await sortedOracles.report(
CeloContract.StableToken,
numerator,
denominator,
nonOracleAddress
)
await expect(tx.sendAndWaitForReceipt()).rejects.toThrow('sender was not an oracle')
})

it('should not change the list of rates', async () => {
const initialRates = await sortedOracles.getRates(CeloContract.StableToken)
try {
const tx = await sortedOracles.report(
CeloContract.StableToken,
numerator,
denominator,
nonOracleAddress
)
await tx.sendAndWaitForReceipt()
} catch (err) {
// We don't need to do anything with this error other than catch it so
// it doesn't fail this test.
} finally {
const resultingRates = await sortedOracles.getRates(CeloContract.StableToken)
expect(resultingRates).toMatchObject(initialRates)
}
})
})
})

/**
* Proxy Calls to view methods
*
* The purpose of these tests is to verify that these wrapper functions exist,
* are calling the contract methods correctly, and get some value back. The
* values checked here are often dependent on setup occuring in the protocol
* migrations run in `yarn test:prepare`. If these tests are failing, the first
* thing to check is if there have been changes to the migrations
*/
describe('#getRates', () => {
beforeEach(async () => {
for (let i = 0; i < stableTokenOracles.length; i++) {
// reports these values:
// 1/2, 2/2, 3/2, 4/2
// resulting in: 0.5, 1, 1.5, 2
const tx = await sortedOracles.report(
CeloContract.StableToken,
i + 1,
2,
stableTokenOracles[i]
)
await tx.sendAndWaitForReceipt()
}
})
it('SBAT getRates', async () => {
const rates = await sortedOracles.getRates(CeloContract.StableToken)
expect(rates.length).toBeGreaterThan(0)
for (const rate of rates) {
expect(rate).toHaveProperty('address')
expect(rate).toHaveProperty('rate')
expect(rate).toHaveProperty('medianRelation')
}
})

it('returns the rate as the result of the calculation numerator/denominator', async () => {
const expectedRates = ['2', '1.5', '1', '0.5']
const response = await sortedOracles.getRates(CeloContract.StableToken)
const actualRates = response.map((r) => r.rate.toString())
expect(actualRates).toEqual(expectedRates)
})
})

describe('#isOracle', () => {
it('returns true when this address is a whitelisted oracle for this token', async () => {
expect(await sortedOracles.isOracle(CeloContract.StableToken, oracleAddress)).toEqual(true)
})
it('returns false when this address is not an oracle', async () => {
expect(await sortedOracles.isOracle(CeloContract.StableToken, nonOracleAddress)).toEqual(
false
)
})
})

describe('#numRates', () => {
it('returns a count of rates reported for the specified token', async () => {
// Why 1? In packages/protocol/08_stabletoken, a single rate is reported
expect(await sortedOracles.numRates(CeloContract.StableToken)).toEqBigNumber(1)
})
})

describe('#medianRate', () => {
it('returns the key for the median', async () => {
const returnedMedian = await sortedOracles.medianRate(CeloContract.StableToken)
// The value `10` comes from: packages/protocol/migrationsConfig.js:
// stableToken.goldPrice
expect(returnedMedian.rate).toEqBigNumber(10)
})
})

describe('#reportExpirySeconds', () => {
it('returns the number of seconds after which a report expires', async () => {
const result = await sortedOracles.reportExpirySeconds()
expect(result).toEqBigNumber(3600)
})
})

/**
* Helper Functions
*
* These are functions in the wrapper that call other functions, passing in
* some regularly used arguments. The purpose of these tests is to verify that
* those arguments are being set correctly.
*/
describe('getStableTokenRates', () => {
it('gets rates for Stable Token', async () => {
const usdRatesResult = await sortedOracles.getStableTokenRates()
const getRatesResult = await sortedOracles.getRates(CeloContract.StableToken)
expect(usdRatesResult).toEqual(getRatesResult)
})
})

describe('reportStableToken', () => {
it('calls report with the address for StableToken', async () => {
const tx = await sortedOracles.reportStableToken(14, 1, oracleAddress)
await tx.sendAndWaitForReceipt()
expect(tx.txo.arguments[0]).toEqual(stableTokenAddress)
})
})
})
Loading

0 comments on commit 9565b53

Please sign in to comment.