Socket
Socket
Sign inDemoInstall

@safe-global/safe-apps-sdk

Package Overview
Dependencies
Maintainers
7
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@safe-global/safe-apps-sdk - npm Package Compare versions

Comparing version 7.9.0 to 7.10.0

6

CHANGELOG.md
# @gnosis.pm/safe-apps-sdk
## 7.10.0
### Minor Changes
- f89c36f: Adds the new `setSafeSettings` and `getOffChainSignature` methods.
## 7.9.0

@@ -4,0 +10,0 @@

2

dist/package.json
{
"name": "@safe-global/safe-apps-sdk",
"version": "7.9.0",
"version": "7.10.0",
"description": "SDK developed to integrate third-party apps with Safe app.",

@@ -5,0 +5,0 @@ "main": "dist/src/index.js",

@@ -11,2 +11,3 @@ export declare enum Methods {

getEnvironmentInfo = "getEnvironmentInfo",
getOffChainSignature = "getOffChainSignature",
requestAddressBook = "requestAddressBook",

@@ -13,0 +14,0 @@ wallet_getPermissions = "wallet_getPermissions",

@@ -15,2 +15,3 @@ "use strict";

Methods["getEnvironmentInfo"] = "getEnvironmentInfo";
Methods["getOffChainSignature"] = "getOffChainSignature";
Methods["requestAddressBook"] = "requestAddressBook";

@@ -17,0 +18,0 @@ Methods["wallet_getPermissions"] = "wallet_getPermissions";

@@ -14,2 +14,3 @@ export declare const RPC_CALLS: {

readonly eth_estimateGas: "eth_estimateGas";
readonly safe_setSettings: "safe_setSettings";
};

@@ -17,3 +17,4 @@ "use strict";

eth_estimateGas: 'eth_estimateGas',
safe_setSettings: 'safe_setSettings',
};
//# sourceMappingURL=constants.js.map

@@ -1,2 +0,2 @@

import { BlockNumberArg, Communicator, Log, BlockTransactionString, BlockTransactionObject, Web3TransactionObject, TransactionConfig, Web3TransactionReceiptObject, PastLogsOptions } from '../types';
import { BlockNumberArg, Communicator, Log, BlockTransactionString, BlockTransactionObject, Web3TransactionObject, TransactionConfig, Web3TransactionReceiptObject, PastLogsOptions, SafeSettings } from '../types';
declare class Eth {

@@ -15,2 +15,3 @@ call: (params?: [TransactionConfig, (string | undefined)?] | undefined) => Promise<string>;

getEstimateGas: (transaction: TransactionConfig) => Promise<number>;
setSafeSettings: (params?: [SafeSettings] | undefined) => Promise<SafeSettings>;
private readonly communicator;

@@ -17,0 +18,0 @@ constructor(communicator: Communicator);

@@ -57,2 +57,5 @@ "use strict";

})([transaction]);
this.setSafeSettings = this.buildRequest({
call: constants_1.RPC_CALLS.safe_setSettings,
});
}

@@ -59,0 +62,0 @@ buildRequest(args) {

@@ -12,2 +12,3 @@ import { Communicator, SafeInfo, ChainInfo, SafeBalances, GetBalanceParams, EnvironmentInfo, AddressBookItem, EIP712TypedData } from '../types';

calculateTypedMessageHash(typedMessage: EIP712TypedData): string;
getOffChainSignature(messageHash: string): Promise<string>;
isMessageSigned(message: string | EIP712TypedData, signature?: string): Promise<boolean>;

@@ -14,0 +15,0 @@ isMessageHashSigned(messageHash: string, signature?: string): Promise<boolean>;

@@ -93,2 +93,6 @@ "use strict";

}
async getOffChainSignature(messageHash) {
const response = await this.communicator.send(methods_1.Methods.getOffChainSignature, messageHash);
return response.data;
}
async isMessageSigned(message, signature = '0x') {

@@ -95,0 +99,0 @@ let check;

@@ -1,2 +0,2 @@

import { GatewayTransactionDetails, SendTransactionsParams, Communicator, SendTransactionsResponse, EIP712TypedData } from '../types';
import { GatewayTransactionDetails, SendTransactionsParams, Communicator, SendTransactionsResponse, EIP712TypedData, SignMessageResponse } from '../types';
declare class TXs {

@@ -6,6 +6,6 @@ private readonly communicator;

getBySafeTxHash(safeTxHash: string): Promise<GatewayTransactionDetails>;
signMessage(message: string): Promise<SendTransactionsResponse>;
signTypedMessage(typedData: EIP712TypedData): Promise<SendTransactionsResponse>;
signMessage(message: string): Promise<SignMessageResponse>;
signTypedMessage(typedData: EIP712TypedData): Promise<SignMessageResponse>;
send({ txs, params }: SendTransactionsParams): Promise<SendTransactionsResponse>;
}
export { TXs };

@@ -17,2 +17,3 @@ import { Methods } from '../communication/methods';

[Methods.getEnvironmentInfo]: EnvironmentInfo;
[Methods.getOffChainSignature]: string;
[Methods.requestAddressBook]: AddressBookItem[];

@@ -19,0 +20,0 @@ [Methods.wallet_getPermissions]: Permission[];

@@ -88,1 +88,4 @@ import { RPC_CALLS } from '../eth/constants';

}
export interface SafeSettings {
offChainSigning?: boolean;
}

@@ -51,2 +51,6 @@ import { ChainInfo as _ChainInfo } from '@safe-global/safe-gateway-typescript-sdk';

};
export type OffChainSignMessageResponse = {
messageHash: string;
};
export type SignMessageResponse = SendTransactionsResponse | OffChainSignMessageResponse;
export type SafeInfo = {

@@ -53,0 +57,0 @@ safeAddress: string;

{
"name": "@safe-global/safe-apps-sdk",
"version": "7.9.0",
"version": "7.10.0",
"description": "SDK developed to integrate third-party apps with Safe app.",

@@ -5,0 +5,0 @@ "main": "dist/src/index.js",

@@ -44,3 +44,3 @@ # Safe Apps SDK

This library exposes a class as a default export. It accepts an optional options object:
`allowedDomains` - Array of regular expressions for origins to accept messages from. If not passed, accepts
`allowedDomains` - Array of regular expressions for origins to accept messages from. If not passed, accepts
messages from all domains

@@ -175,2 +175,42 @@ `debug` - Boolean. If enabled, it will log outgoing/incoming messages.

#### Off-chain signing
Signing a message off-chain first requires dispatching a `safe_setSettings` RPC call (via `sdk.eth.setSafeSettings()`) with the `offChainSigning` flag set to `true`. Then the relevant `signMessage`/`signTypedData` needs to be called, proposing a message to our services that can then be approved by Safe owners.
```js
const settings = {
offChainSigning: true,
};
const currentSettings = await appsSdk.eth.setSafeSettings([settings]);
const message = "I'm the owner of wallet 0x000000";
const hash = await sdk.txs.signMessage(message);
// { messageHash: '0x...' }
const typedMessage = {
...
}
const hash = await sdk.txs.signTypedMessage(typedMessage);
// { messageHash: '0x...' }
```
Signing returns the `messageHash` of the proposed [`SafeMessage`](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L12) which can be used to fetch the off-chain signature with.
```js
const offChainSignature = await sdk.safe.getOffChainSignature(messageHash);
// '0x123'
```
The returned signature will either be an empty string or valid one once the required number of Safe owners have confirmed the message.
To validate the signature, use `sdk.safe.isMessageSigned()`, passing the signature as the second argument.
```js
const message = "I'm the owner of wallet 0x000000";
const messageIsSigned = await sdk.safe.isMessageSigned(message, signature);
```
#### On-chain signing
Because the Safe is a smart contract wallet, it doesn't have a private key that the wallet can use to sign messages. Instead, we have a library to sign messages, and the validation logic follows [EIP-1271 - Standard Signature Validation Method for Contracts](https://eips.ethereum.org/EIPS/eip-1271). Signing a message with the Safe requires sending a Safe transaction that needs to be approved by Safe owners. To dive into the smart contract implementation, you can start with [library tests](https://github.com/safe-global/safe-contracts/blob/ee92957307653ae6cf7312bbcb1a13c6884ea6ea/test/libraries/SignMessageLib.spec.ts) in the safe-contracts repo.

@@ -420,2 +460,16 @@

### setSafeSettings
Sets settings of the currently opened Safe.
> Note: Returns the new `SafeSettings`.
```js
const settings = {
offChainSigning: true,
};
const success = await appsSdk.eth.setSafeSettings([settings]);
```
## Testing in the Safe application

@@ -422,0 +476,0 @@

@@ -11,2 +11,3 @@ export enum Methods {

getEnvironmentInfo = 'getEnvironmentInfo',
getOffChainSignature = 'getOffChainSignature',
requestAddressBook = 'requestAddressBook',

@@ -13,0 +14,0 @@ wallet_getPermissions = 'wallet_getPermissions',

@@ -14,2 +14,3 @@ export const RPC_CALLS = {

eth_estimateGas: 'eth_estimateGas',
safe_setSettings: 'safe_setSettings',
} as const;

@@ -354,2 +354,23 @@ import SDK from '../index';

});
describe('setSafeSettings', () => {
it('Should send valid, Safe-specific settings to the interface', () => {
sdkInstance.eth.setSafeSettings([
{
offChainSigning: true,
},
]);
expect(spy).toHaveBeenCalledWith(
expect.objectContaining({
method: Methods.rpcCall,
params: {
call: 'safe_setSettings',
params: [{ offChainSigning: true }],
},
}),
'*',
);
});
});
});

@@ -14,2 +14,3 @@ import { RPC_CALLS } from '../eth/constants';

PastLogsOptions,
SafeSettings,
} from '../types';

@@ -46,2 +47,3 @@ import { Methods } from '../communication/methods';

public getEstimateGas;
public setSafeSettings;

@@ -99,2 +101,5 @@ private readonly communicator: Communicator;

})([transaction]);
this.setSafeSettings = this.buildRequest<[SafeSettings], SafeSettings>({
call: RPC_CALLS.safe_setSettings,
});
}

@@ -101,0 +106,0 @@

@@ -127,2 +127,11 @@ import { ethers } from 'ethers';

async getOffChainSignature(messageHash: string): Promise<string> {
const response = await this.communicator.send<Methods.getOffChainSignature, string, string>(
Methods.getOffChainSignature,
messageHash,
);
return response.data;
}
async isMessageSigned(message: string | EIP712TypedData, signature = '0x'): Promise<boolean> {

@@ -129,0 +138,0 @@ let check: (() => Promise<boolean>) | undefined;

@@ -380,2 +380,13 @@ import SDK from '../sdk';

describe('SDK.safe.getOffChainSignature', () => {
test('Should request the off-chain signature from the interface', () => {
sdkInstance.safe.getOffChainSignature('0x123');
expect(postMessageSpy).toHaveBeenCalledWith(
expect.objectContaining({ method: Methods.getOffChainSignature, params: '0x123' }),
'*',
);
});
});
describe('SDK.safe.requestAddressBook', () => {

@@ -382,0 +393,0 @@ const wrongPermissions = [

@@ -12,2 +12,3 @@ import { Methods } from '../communication/methods';

isObjectEIP712TypedData,
SignMessageResponse,
} from '../types';

@@ -36,3 +37,3 @@

async signMessage(message: string): Promise<SendTransactionsResponse> {
async signMessage(message: string): Promise<SignMessageResponse> {
const messagePayload = {

@@ -42,3 +43,3 @@ message,

const response = await this.communicator.send<Methods.signMessage, SignMessageParams, SendTransactionsResponse>(
const response = await this.communicator.send<Methods.signMessage, SignMessageParams, SignMessageResponse>(
Methods.signMessage,

@@ -51,3 +52,3 @@ messagePayload,

async signTypedMessage(typedData: EIP712TypedData): Promise<SendTransactionsResponse> {
async signTypedMessage(typedData: EIP712TypedData): Promise<SignMessageResponse> {
if (!isObjectEIP712TypedData(typedData)) {

@@ -60,3 +61,3 @@ throw new Error('Invalid typed data');

SignTypedMessageParams,
SendTransactionsResponse
SignMessageResponse
>(Methods.signTypedMessage, { typedData });

@@ -63,0 +64,0 @@

@@ -20,2 +20,3 @@ import { Methods } from '../communication/methods';

[Methods.getEnvironmentInfo]: EnvironmentInfo;
[Methods.getOffChainSignature]: string;
[Methods.requestAddressBook]: AddressBookItem[];

@@ -22,0 +23,0 @@ [Methods.wallet_getPermissions]: Permission[];

@@ -100,1 +100,5 @@ import { RPC_CALLS } from '../eth/constants';

}
export interface SafeSettings {
offChainSigning?: boolean;
}

@@ -65,2 +65,8 @@ import { ChainInfo as _ChainInfo } from '@safe-global/safe-gateway-typescript-sdk';

export type OffChainSignMessageResponse = {
messageHash: string;
};
export type SignMessageResponse = SendTransactionsResponse | OffChainSignMessageResponse;
export type SafeInfo = {

@@ -67,0 +73,0 @@ safeAddress: string;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc