Skip to content

Commit

Permalink
Merge tag 'v28.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
jyap808 committed Jun 30, 2022
2 parents 4bb64ca + afc6ee7 commit f8447b7
Show file tree
Hide file tree
Showing 37 changed files with 1,605 additions and 330 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* text=auto

yarn.lock linguist-generated=false
32 changes: 29 additions & 3 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v2
with:
# We check out the release pull request's base branch, which will be
# used as the base branch for all git operations.
ref: ${{ github.event.pull_request.base.ref }}
ref: ${{ github.sha }}
- name: Get Node.js version
id: nvm
run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc)
Expand All @@ -27,3 +25,31 @@ jobs:
- uses: MetaMask/action-publish-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
yarn setup
yarn build
- uses: actions/cache@v3
id: restore-build
with:
path: ./dist
key: ${{ github.sha }}

publish-npm:
environment: npm-publish
runs-on: ubuntu-latest
needs: publish-release
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.sha }}
- uses: actions/cache@v3
id: restore-build
with:
path: ./dist
key: ${{ github.sha }}
# Set `ignore-scripts` to skip `prepublishOnly` because the release was built already in the previous job
- run: npm config set ignore-scripts true
- name: Publish
uses: MetaMask/action-npm-publish@v1.0.0
with:
npm-token: ${{ secrets.NPM_TOKEN }}
32 changes: 31 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [28.0.0]
### Added
- Add GrantPermissions action to PermissionsController ([#780](https://github.com/MetaMask/controllers/pull/780))
- Add `PermissionController.revokePermissionForAllSubjects` action ([#764](https://github.com/MetaMask/controllers/pull/764))

### Changed
- **BREAKING:** Rename NotificationController to AnnouncementController ([#697](https://github.com/MetaMask/controllers/pull/697))
- The `NotificationController` class is now `AnnouncementController`.
- The controller `notifications` state has been renamed to `announcements`.
- All other exported types including the word "notification" have been updated to use the word "announcement" instead.

## [27.1.1]
### Fixed
- Move `@keystonehq/metamask-airgapped-keyring` to dependencies ([#757](https://github.com/MetaMask/controllers/pull/757))

## [27.1.0] [DEPRECATED]
### Added
- Now the `KeyringController` supports the `QRKeyring` from `@keystonehq/metamask-airgapped-keyring`. Developers can enable the import of accounts from a QR hardware wallet. A new optional parameter, `setAccountLabel` from the `PreferencesController`, should be passed to the `KeyringController` to enable this new functionality. ([#685](https://github.com/MetaMask/controllers/pull/685))
- **UPDATE:** This is broken. Consumers are encouraged to upgrade to [27.1.1].

### Changed
- Bump `eth-phishing-detect` version from 1.1.14 to 1.1.16 ([#742](https://github.com/MetaMask/controllers/pull/742))
- Bump `@metamask/contract-metadata` from 1.31.0 to 1.33.0 ([#730](https://github.com/MetaMask/controllers/pull/730))

### Fixed
- Improve error message when attempting to import an invalid private key ([#739](https://github.com/MetaMask/controllers/pull/739))

## [27.0.0]
### Changed
- **BREAKING:** Further reduce load on Infura by removing non-critical data from the fallback implementation of the Gas API ([#712](https://github.com/MetaMask/controllers/pull/712))
Expand Down Expand Up @@ -522,7 +549,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
- Remove shapeshift controller (#209)

[Unreleased]: https://github.com/MetaMask/controllers/compare/v27.0.0...HEAD
[Unreleased]: https://github.com/MetaMask/controllers/compare/v28.0.0...HEAD
[28.0.0]: https://github.com/MetaMask/controllers/compare/v27.1.1...v28.0.0
[27.1.1]: https://github.com/MetaMask/controllers/compare/v27.1.0...v27.1.1
[27.1.0]: https://github.com/MetaMask/controllers/compare/v27.0.0...v27.1.0
[27.0.0]: https://github.com/MetaMask/controllers/compare/v26.0.0...v27.0.0
[26.0.0]: https://github.com/MetaMask/controllers/compare/v25.1.0...v26.0.0
[25.1.0]: https://github.com/MetaMask/controllers/compare/v25.0.0...v25.1.0
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,6 @@ The project follows the same release process as the other libraries in the MetaM

7. Publish the release on npm.

- Be very careful to use a clean local environment to publish the release, and follow exactly the same steps used during CI.
- Use `npm publish --dry-run` to examine the release contents to ensure the correct files are included. Compare to previous releases if necessary (e.g. using `https://unpkg.com/browse/[package name]@[package version]/`).
- Once you are confident the release contents are correct, publish the release using `npm publish`.
- Wait for the `publish-release` GitHub Action workflow to finish. This should trigger a second job (`publish-npm`), which will wait for a run approval by the [`npm publishers`](https://github.com/orgs/MetaMask/teams/npm-publishers) team.
- Approve the `publish-npm` job (or ask somebody on the npm publishers team to approve it for you).
- Once the `publish-npm` job has finished, check npm to verify that it has been published.
14 changes: 14 additions & 0 deletions __mocks__/uuid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const uuid = require('uuid');

// mock the v4 function of uuid lib to make sure it returns the fixed id for testing
const v4 = () => '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d';

module.exports.NIL = uuid.NIL;
module.exports.v1 = uuid.v1;
module.exports.v3 = uuid.v3;
module.exports.v5 = uuid.v5;
module.exports.parse = uuid.parse;
module.exports.validate = uuid.validate;
module.exports.stringify = uuid.stringify;

module.exports.v4 = v4;
21 changes: 13 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sparrow-controllers",
"version": "27.0.3",
"version": "28.0.0",
"description": "Collection of platform-agnostic modules for creating secure data models for cryptocurrency wallets",
"keywords": [
"Sparrow",
Expand Down Expand Up @@ -29,14 +29,15 @@
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write",
"test": "jest",
"test:watch": "jest --watch",
"build": "rimraf dist && tsc --project .",
"build": "rimraf dist && tsc --project tsconfig.build.json",
"build:watch": "yarn build --watch",
"build:link": "yarn build && cd dist && yarn link && rm -rf node_modules && cd ..",
"doc": "typedoc && touch docs/.nojekyll"
},
"dependencies": {
"@ethereumjs/common": "^2.3.1",
"@ethereumjs/tx": "^3.2.1",
"@keystonehq/metamask-airgapped-keyring": "^0.3.0",
"@metamask/metamask-eth-abis": "3.0.0",
"@metamask/types": "^1.1.0",
"@types/uuid": "^8.3.0",
Expand All @@ -48,7 +49,7 @@
"eth-json-rpc-infura": "^5.1.0",
"eth-keyring-controller": "^6.2.1",
"eth-method-registry": "1.1.0",
"eth-phishing-detect": "^1.1.14",
"eth-phishing-detect": "^1.1.16",
"eth-query": "^2.1.2",
"eth-rpc-errors": "^4.0.0",
"eth-sig-util": "^3.0.0",
Expand All @@ -71,7 +72,8 @@
"web3-provider-engine": "^16.0.3"
},
"devDependencies": {
"@lavamoat/allow-scripts": "^1.0.6",
"@keystonehq/bc-ur-registry-eth": "^0.9.0",
"@lavamoat/allow-scripts": "^2.0.2",
"@metamask/auto-changelog": "^2.5.0",
"@metamask/eslint-config": "^9.0.0",
"@metamask/eslint-config-jest": "^9.0.0",
Expand Down Expand Up @@ -117,10 +119,13 @@
"lavamoat": {
"allowScripts": {
"@lavamoat/preinstall-always-fail": false,
"core-js": false,
"keccak": true,
"secp256k1": true,
"sha3": true
"@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": true,
"babel-runtime>core-js": false,
"eth-sig-util>ethereumjs-abi>ethereumjs-util>keccakjs>sha3": true,
"eth-sig-util>ethereumjs-util>keccak": true,
"eth-sig-util>ethereumjs-util>secp256k1": true,
"ethereumjs-util>ethereum-cryptography>keccak": true,
"ethereumjs-util>ethereum-cryptography>secp256k1": true
}
}
}
97 changes: 97 additions & 0 deletions src/announcement/AnnouncementController.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {
AnnouncementConfig,
AnnouncementState,
AnnouncementController,
StateAnnouncementMap,
} from './AnnouncementController';

const config1: AnnouncementConfig = {
allAnnouncements: {
1: {
id: 1,
date: '12/8/2020',
},
2: {
id: 2,
date: '12/8/2020',
},
},
};

const config2: AnnouncementConfig = {
allAnnouncements: {
1: {
id: 1,
date: '12/8/2020',
},
2: {
id: 2,
date: '12/8/2020',
},
3: {
id: 3,
date: '12/8/2020',
},
},
};

const state1: AnnouncementState = {
announcements: {
1: {
id: 1,
date: '12/8/2020',
isShown: true,
},
2: {
id: 2,
date: '12/8/2020',
isShown: true,
},
},
};

describe('announcement controller', () => {
it('should add announcement to state', () => {
const controller = new AnnouncementController(config1);
expect(Object.keys(controller.state.announcements)).toHaveLength(2);
const expectedStateNotifications: StateAnnouncementMap = {
1: {
...config1.allAnnouncements[1],
isShown: false,
},
2: {
...config1.allAnnouncements[2],
isShown: false,
},
};
expect(controller.state.announcements).toStrictEqual(
expectedStateNotifications,
);
});

it('should add new announcement to state', () => {
const controller = new AnnouncementController(config2, state1);
expect(Object.keys(controller.state.announcements)).toHaveLength(3);
expect(controller.state.announcements[1].isShown).toBe(true);
expect(controller.state.announcements[2].isShown).toBe(true);
expect(controller.state.announcements[3].isShown).toBe(false);
});

describe('update viewed announcements', () => {
it('should update isShown status', () => {
const controller = new AnnouncementController(config2);
controller.updateViewed({ 1: true });
expect(controller.state.announcements[1].isShown).toBe(true);
expect(controller.state.announcements[2].isShown).toBe(false);
expect(controller.state.announcements[3].isShown).toBe(false);
});

it('should update isShown of more than one announcement', () => {
const controller = new AnnouncementController(config2);
controller.updateViewed({ 2: true, 3: true });
expect(controller.state.announcements[1].isShown).toBe(false);
expect(controller.state.announcements[2].isShown).toBe(true);
expect(controller.state.announcements[3].isShown).toBe(true);
});
});
});
106 changes: 106 additions & 0 deletions src/announcement/AnnouncementController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { BaseController, BaseConfig, BaseState } from '../BaseController';

interface ViewedAnnouncement {
[id: number]: boolean;
}

interface Announcement {
id: number;
date: string;
}

interface StateAnnouncement extends Announcement {
isShown: boolean;
}

/**
* A map of announcement ids to Announcement objects
*/
interface AnnouncementMap {
[id: number]: Announcement;
}

/**
* A map of announcement ids to StateAnnouncement objects
*/
export interface StateAnnouncementMap {
[id: number]: StateAnnouncement;
}

/**
* AnnouncementConfig will hold the active announcements
*/
export interface AnnouncementConfig extends BaseConfig {
allAnnouncements: AnnouncementMap;
}

/**
* Announcement state will hold all the seen and unseen announcements
* that are still active
*/
export interface AnnouncementState extends BaseState {
announcements: StateAnnouncementMap;
}

const defaultState = {
announcements: {},
};

/**
* Controller for managing in-app announcements.
*/
export class AnnouncementController extends BaseController<
AnnouncementConfig,
AnnouncementState
> {
/**
* Creates a AnnouncementController instance.
*
* @param config - Initial options used to configure this controller.
* @param state - Initial state to set on this controller.
*/
constructor(config: AnnouncementConfig, state?: AnnouncementState) {
super(config, state || defaultState);
this.initialize();
this._addAnnouncements();
}

/**
* Compares the announcements in state with the announcements from file
* to check if there are any new announcements
* if yes, the new announcement will be added to the state with a flag indicating
* that the announcement is not seen by the user.
*/
private _addAnnouncements(): void {
const newAnnouncements: StateAnnouncementMap = {};
const { allAnnouncements } = this.config;
Object.values(allAnnouncements).forEach(
(announcement: StateAnnouncement) => {
newAnnouncements[announcement.id] = this.state.announcements[
announcement.id
]
? this.state.announcements[announcement.id]
: {
...announcement,
isShown: false,
};
},
);
this.update({ announcements: newAnnouncements });
}

/**
* Updates the status of the status of the specified announcements
* once it is read by the user.
*
* @param viewedIds - The announcement IDs to mark as viewed.
*/
updateViewed(viewedIds: ViewedAnnouncement): void {
const stateAnnouncements = this.state.announcements;

for (const id of Object.keys(viewedIds).map(Number)) {
stateAnnouncements[id].isShown = viewedIds[id];
}
this.update({ announcements: stateAnnouncements }, true);
}
}
Loading

0 comments on commit f8447b7

Please sign in to comment.