Skip to content

Commit

Permalink
feat: add authorization
Browse files Browse the repository at this point in the history
  • Loading branch information
bangjelkoski committed Nov 23, 2024
1 parent 2f93101 commit 76b6e0a
Show file tree
Hide file tree
Showing 12 changed files with 475 additions and 62 deletions.
16 changes: 16 additions & 0 deletions etc/jest-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const mjsResolver = (path, options) => {
const mjsExtRegex = /\.js$/i
const resolver = options.defaultResolver

if (mjsExtRegex.test(path)) {
try {
return resolver(path.replace(mjsExtRegex, '.ts'), options)
} catch (e) {
// use default resolver
}
}

return resolver(path, options)
}

module.exports = mjsResolver
17 changes: 12 additions & 5 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const directoryPaths = Object.keys(compilerOptions.paths).reduce(
{},
)


// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html

Expand Down Expand Up @@ -76,13 +77,12 @@ module.exports = {
// globalTeardown: null,

// A set of global variables that need to be available in all test environments
// globals: {},

// An array of directory names to be searched recursively up from the requiring module's location
moduleDirectories: ['node_modules', '<rootDir>/src'],

// An array of file extensions your modules use
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx'],
moduleFileExtensions: ['ts', 'js'],

// A map from regular expressions to module names that allow to stub out resources with a single module
moduleNameMapper: {
Expand All @@ -100,7 +100,7 @@ module.exports = {
// notifyMode: "failure-change",

// A preset that is used as a base for Jest's configuration
preset: 'ts-jest',
preset: 'ts-jest/presets/default-esm',

// Run tests from one or more projects
// projects: null,
Expand All @@ -115,7 +115,7 @@ module.exports = {
// resetModules: false,

// A path to a custom resolver
// resolver: null,
resolver: './etc/jest-resolver.js',

// Automatically restore mock state between every test
// restoreMocks: false,
Expand Down Expand Up @@ -170,10 +170,17 @@ module.exports = {

// A map from regular expressions to paths to transformers
transform: {
'^.+\\.ts?$': 'ts-jest',
'^.+\\.ts?$': [
'ts-jest',
{
useESM: true,
},
],
'^.+\\.js?$': 'babel-jest',
},

extensionsToTreatAsEsm: ['.ts'],

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
transformIgnorePatterns: ['^.+\\.json$', 'node_modules/(?!(eth-crypto)/)'],

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,15 @@
"husky": "^7.0.2",
"jest": "^29.4.3",
"jest-junit": "^15.0.0",
"jest-resolve": "^29.7.0",
"lerna": "6.6.1",
"lint-staged": "^11.1.2",
"live-server": "^1.2.1",
"markdownlint-cli": "^0.28.1",
"prettier": "^2.4.1",
"serve": "^12.0.1",
"shx": "^0.3.4",
"ts-jest": "^29.0.5",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"ts-node-dev": "2.0.0",
"tsc-alias": "^1.7.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk-ts/src/core/modules/authz/msgs/MsgExec.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import MsgExec from './MsgExec.js'
import MsgExec from './MsgExec'
import { mockFactory } from '@injectivelabs/test-utils'
import { BigNumberInBase } from '@injectivelabs/utils'
import { MsgSend } from '../../bank/index.js'
import MsgSend from '../../bank/msgs/MsgSend.js'

const { injectiveAddress, injectiveAddress2 } = mockFactory

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
import MsgGrantWithAuthorization from './MsgGrantWithAuthorization.js'
import { mockFactory } from '@injectivelabs/test-utils'
import GenericAuthorization from './grants/GenericAuthorization.js'
import ContractExecutionAuthorization from './grants/ContractExecutionAuthorization.js'

const { injectiveAddress, injectiveAddress2 } = mockFactory

describe('MsgGrantWithAuthorization', () => {
describe('GenericAuthorization', () => {
const params: MsgGrantWithAuthorization['params'] = {
grantee: injectiveAddress,
granter: injectiveAddress2,
authorization: GenericAuthorization.fromJSON({
messageTypeUrl: '/cosmos.bank.v1beta1.MsgSend',
}),
expiration: 1800000000,
}

const any = params.authorization.toAny()
const protoType = '/cosmos.authz.v1beta1.MsgGrant'
const protoTypeShort = 'cosmos-sdk/MsgGrant'
const protoParamsGenericAuthorization = {
grantee: params.grantee,
granter: params.granter,
grant: {
authorization: {
typeUrl: any.typeUrl,
value: new Uint8Array(Buffer.from(any.value)),
},
expiration: new Date(params.expiration! * 1000),
},
}

const protoParamsGenericAuthorizationAmino = {
grantee: params.grantee,
granter: params.granter,
grant: {
authorization: params.authorization.toAmino(),
expiration: new Date(params.expiration! * 1000),
},
}
const protoParamsGenericAuthorizationWeb3 = {
grantee: params.grantee,
granter: params.granter,
grant: {
authorization: params.authorization.toWeb3(),
expiration: new Date(params.expiration! * 1000),
},
}
const message = MsgGrantWithAuthorization.fromJSON(params)

it('generates proper proto', () => {
const proto = message.toProto()

expect(proto).toStrictEqual({
...protoParamsGenericAuthorization,
})
})

it('generates proper data', () => {
const data = message.toData()

expect(data).toStrictEqual({
'@type': protoType,
...protoParamsGenericAuthorization,
})
})

it('generates proper amino', () => {
const amino = message.toAmino()

expect(amino).toStrictEqual({
type: protoTypeShort,
value: protoParamsGenericAuthorizationAmino,
})
})

it('generates proper Eip712 types', () => {
const eip712Types = message.toEip712Types()

expect(Object.fromEntries(eip712Types)).toStrictEqual({
TypeGrant: [
{ name: 'authorization', type: 'TypeGrantAuthorization' },
{ name: 'expiration', type: 'string' },
],
TypeGrantAuthorization: [
{ name: 'type', type: 'string' },
{ name: 'value', type: 'TypeGrantAuthorizationValue' },
],
TypeGrantAuthorizationValue: [{ name: 'msg', type: 'string' }],
MsgValue: [
{ name: 'granter', type: 'string' },
{ name: 'grantee', type: 'string' },
{ name: 'grant', type: 'TypeGrant' },
],
})
})

it('generates proper Eip712 values', () => {
const eip712 = message.toEip712()

expect(eip712).toStrictEqual({
type: 'cosmos-sdk/MsgGrant',
value: {
granter: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
grantee: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
grant: {
authorization: {
type: 'cosmos-sdk/GenericAuthorization',
value: { msg: '/cosmos.bank.v1beta1.MsgSend' },
},
expiration: '2027-01-15T08:00:00Z',
},
},
})
})

it('generates proper web3', () => {
const web3 = message.toWeb3()

expect(web3).toStrictEqual({
'@type': protoType,
...protoParamsGenericAuthorizationWeb3,
})
})
})

describe('ContractExecutionAuthorization', () => {
const params: MsgGrantWithAuthorization['params'] = {
grantee: injectiveAddress,
granter: injectiveAddress2,
authorization: ContractExecutionAuthorization.fromJSON({
contract: injectiveAddress,
limit: {
maxCalls: 100,
},
filter: {
acceptedMessagesKeys: ['set_routes'],
},
}),
expiration: 1800000000,
}

const any = params.authorization.toAny()
const protoType = '/cosmos.authz.v1beta1.MsgGrant'
const protoTypeShort = 'cosmos-sdk/MsgGrant'
const protoParamsContractExecutionAuthorization = {
grantee: params.grantee,
granter: params.granter,
grant: {
authorization: {
typeUrl: any.typeUrl,
value: new Uint8Array(Buffer.from(any.value)),
},
expiration: new Date(params.expiration! * 1000),
},
}

const protoParamsContractExecutionAuthorizationAmino = {
grantee: params.grantee,
granter: params.granter,
grant: {
authorization: params.authorization.toAmino(),
expiration: new Date(params.expiration! * 1000),
},
}
const protoParamsContractExecutionAuthorizationWeb3 = {
grantee: params.grantee,
granter: params.granter,
grant: {
authorization: params.authorization.toWeb3(),
expiration: new Date(params.expiration! * 1000),
},
}
const message = MsgGrantWithAuthorization.fromJSON(params)

it('generates proper proto', () => {
const proto = message.toProto()

expect(proto).toStrictEqual({
...protoParamsContractExecutionAuthorization,
})
})

it('generates proper data', () => {
const data = message.toData()

expect(data).toStrictEqual({
'@type': protoType,
...protoParamsContractExecutionAuthorization,
})
})

it('generates proper amino', () => {
const amino = message.toAmino()

expect(amino).toStrictEqual({
type: protoTypeShort,
value: protoParamsContractExecutionAuthorizationAmino,
})
})

it('generates proper Eip712 types', () => {
const eip712Types = message.toEip712Types()

expect(Object.fromEntries(eip712Types)).toStrictEqual({
TypeGrant: [
{ name: 'authorization', type: 'TypeGrantAuthorization' },
{ name: 'expiration', type: 'string' },
],
TypeGrantAuthorization: [
{ name: 'type', type: 'string' },
{ name: 'grants', type: 'TypeGrantAuthorizationGrants[]' },
],
TypeGrantAuthorizationGrants: [
{ name: 'contract', type: 'string' },
{ name: 'limit', type: 'TypeGrantAuthorizationGrantsLimit' },
{ name: 'filter', type: 'TypeGrantAuthorizationGrantsFilter' },
],
TypeGrantAuthorizationGrantsLimit: [
{ name: 'type', type: 'string' },
{ name: 'remaining', type: 'uint64' },
],
TypeGrantAuthorizationGrantsFilter: [
{ name: 'type', type: 'string' },
{ name: 'keys', type: 'string[]' },
],
MsgValue: [
{ name: 'granter', type: 'string' },
{ name: 'grantee', type: 'string' },
{ name: 'grant', type: 'TypeGrant' },
],
})
})

it('generates proper Eip712 values', () => {
const eip712 = message.toEip712()

expect(eip712).toStrictEqual({
type: 'cosmos-sdk/MsgGrant',
value: {
granter: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
grantee: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
grant: {
authorization: {
type: 'wasm/ContractExecutionAuthorization',
grants: [
{
contract: 'inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku',
limit: { type: 'wasm/MaxCallsLimit', remaining: 100 },
filter: {
type: 'wasm/AcceptedMessageKeysFilter',
keys: ['set_routes'],
},
},
],
},
expiration: '2027-01-15T08:00:00Z',
},
},
})
})

it('generates proper web3', () => {
const web3 = message.toWeb3()

expect(web3).toStrictEqual({
'@type': protoType,
...protoParamsContractExecutionAuthorizationWeb3,
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { BaseAuthorization } from './grants/Base.js'

export declare namespace MsgGrantWithAuthorization {
export interface Params {
authorization: BaseAuthorization<unknown, unknown>
authorization: BaseAuthorization<unknown, unknown, unknown>
grantee: string
granter: string
expiration?: number
Expand Down
Loading

0 comments on commit 76b6e0a

Please sign in to comment.