This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import { i18n } from '../i18n'
|
||||
import { sdk } from '../sdk'
|
||||
import { dataDir, SPACED_CHAIN } from '../utils'
|
||||
|
||||
const { InputSpec, Value } = sdk
|
||||
|
||||
const BACKUP_DIR = `${dataDir}/${SPACED_CHAIN}/wallets_backup`
|
||||
const BACKUP_PATH = `${BACKUP_DIR}/default.json`
|
||||
const WALLET_DIR = `${dataDir}/${SPACED_CHAIN}/wallets/default`
|
||||
const COOKIE_PATH = `${dataDir}/${SPACED_CHAIN}/.cookie`
|
||||
|
||||
const inputSpec = InputSpec.of({
|
||||
walletJson: Value.textarea({
|
||||
name: i18n('Wallet JSON'),
|
||||
description: i18n('Paste the JSON contents of a default.json wallet export.'),
|
||||
warning: null,
|
||||
footnote: null,
|
||||
default: null,
|
||||
required: true,
|
||||
minLength: 1,
|
||||
maxLength: null,
|
||||
placeholder: '{...}',
|
||||
}),
|
||||
})
|
||||
|
||||
export const importWallet = sdk.Action.withInput(
|
||||
// id
|
||||
'import-wallet',
|
||||
|
||||
// metadata
|
||||
async ({ effects }) => ({
|
||||
name: i18n('Import Wallet'),
|
||||
description: i18n(
|
||||
'Restore a previously-exported default.json wallet into spaced.',
|
||||
),
|
||||
warning: i18n(
|
||||
'Existing /data/mainnet/wallets_backup/default.json and /data/mainnet/wallets/default will be renamed with .bakNNN suffixes before the import. The active spaced daemon will load the imported wallet on success.',
|
||||
),
|
||||
allowedStatuses: 'only-running',
|
||||
group: null,
|
||||
visibility: 'enabled',
|
||||
}),
|
||||
|
||||
// input
|
||||
inputSpec,
|
||||
|
||||
// prefill
|
||||
async ({ effects }) => {},
|
||||
|
||||
// run
|
||||
async ({ effects, input }) => {
|
||||
// Validate JSON before touching disk.
|
||||
try {
|
||||
JSON.parse(input.walletJson)
|
||||
} catch (e) {
|
||||
return {
|
||||
version: '1',
|
||||
title: i18n('Failure'),
|
||||
message: i18n('Could not parse wallet JSON: ${error}', {
|
||||
error: (e as Error).message,
|
||||
}),
|
||||
result: null,
|
||||
}
|
||||
}
|
||||
|
||||
// base64-encode so shell quoting can never break on user content.
|
||||
const b64 = Buffer.from(input.walletJson, 'utf8').toString('base64')
|
||||
|
||||
const script = `set -e
|
||||
mkdir -p '${BACKUP_DIR}'
|
||||
|
||||
# Rotate /data/mainnet/wallets_backup/default.json -> .bakNNN if exists.
|
||||
BACKUP='${BACKUP_PATH}'
|
||||
if [ -e "$BACKUP" ]; then
|
||||
i=0
|
||||
while [ -e "$(printf '%s.bak%03d' "$BACKUP" "$i")" ]; do
|
||||
i=$((i+1))
|
||||
done
|
||||
mv "$BACKUP" "$(printf '%s.bak%03d' "$BACKUP" "$i")"
|
||||
fi
|
||||
|
||||
# Write fresh default.json from base64 payload.
|
||||
printf '%s' '${b64}' | base64 -d > "$BACKUP"
|
||||
|
||||
# Rotate /data/mainnet/wallets/default folder -> .bakNNN if exists.
|
||||
WDIR='${WALLET_DIR}'
|
||||
if [ -d "$WDIR" ]; then
|
||||
j=0
|
||||
while [ -d "$(printf '%s.bak%03d' "$WDIR" "$j")" ]; do
|
||||
j=$((j+1))
|
||||
done
|
||||
mv "$WDIR" "$(printf '%s.bak%03d' "$WDIR" "$j")"
|
||||
fi
|
||||
|
||||
# Import + load via spaced RPC.
|
||||
/root/.cargo/bin/space-cli --chain ${SPACED_CHAIN} --rpc-cookie '${COOKIE_PATH}' importwallet "$BACKUP"
|
||||
/root/.cargo/bin/space-cli --chain ${SPACED_CHAIN} --rpc-cookie '${COOKIE_PATH}' loadwallet
|
||||
`
|
||||
|
||||
const res = await sdk.SubContainer.withTemp(
|
||||
effects,
|
||||
{ imageId: 'spaces' },
|
||||
sdk.Mounts.of().mountVolume({
|
||||
volumeId: 'main',
|
||||
subpath: null,
|
||||
mountpoint: dataDir,
|
||||
readonly: false,
|
||||
}),
|
||||
'spaces-import-wallet',
|
||||
(subc) => subc.exec(['bash', '-c', script], { user: 'root' }),
|
||||
)
|
||||
|
||||
if (res.exitCode !== 0) {
|
||||
const stderr = (res.stderr ?? '').toString()
|
||||
const stdout = (res.stdout ?? '').toString()
|
||||
return {
|
||||
version: '1',
|
||||
title: i18n('Failure'),
|
||||
message: i18n('Could not import wallet: ${error}', {
|
||||
error: stderr || stdout || `exit ${res.exitCode}`,
|
||||
}),
|
||||
result: null,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
version: '1',
|
||||
title: i18n('Success'),
|
||||
message: i18n('Wallet imported and loaded.'),
|
||||
result: null,
|
||||
}
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user