Setup handler to migrate SC ledger accounts to Database Players

This commit is contained in:
Hammad Jutt
2020-08-15 23:53:08 -06:00
parent bcb69ad307
commit c27c77eb74
9 changed files with 179 additions and 7 deletions

View File

@@ -0,0 +1,7 @@
alter table "public"."Account" drop constraint "Account_identifier_type_key";
alter table "public"."Account" add constraint "Account_identifier_key" unique ("identifier");
ALTER TABLE "public"."Player" DROP COLUMN "scIdentityId";
ALTER TABLE "public"."Player" ALTER COLUMN "ethereum_address" SET NOT NULL;

View File

@@ -0,0 +1,7 @@
ALTER TABLE "public"."Player" ALTER COLUMN "ethereum_address" DROP NOT NULL;
ALTER TABLE "public"."Player" ADD COLUMN "scIdentityId" Text NULL UNIQUE;
alter table "public"."Account" drop constraint "Account_identifier_unique_key";
alter table "public"."Account" add constraint "Account_identifier_type_key" unique ("identifier", "type");

View File

@@ -14,8 +14,7 @@ generates:
./src/lib/autogen/sdk.ts:
schema: '../codegen/schema.graphql'
documents:
- ./src/handlers/**/(!(*.d)).ts
- ./src/handlers/**/*.graphql
- ./src/handlers/graphql/**/(!(*.d)).ts
plugins:
- typescript
- typescript-operations
@@ -24,3 +23,5 @@ generates:
content: '/* eslint-disable */'
config:
immutableTypes: true
scalars:
account_type: "'ETHEREUM' | 'DISCORD' | 'GITHUB' | 'TWITTER' | 'DISCOURSE'"

View File

@@ -0,0 +1,82 @@
import { Request, Response } from 'express';
import fetch from 'node-fetch';
import {
Account_Constraint,
Account_Update_Column,
Player_Constraint,
Player_Update_Column,
Scalars,
} from '../../../lib/autogen/sdk';
import { client } from '../../../lib/hasuraClient';
import { AddressBookEntry, SCAccountsData } from './types';
const ACCOUNTS_FILE =
'https://raw.githubusercontent.com/MetaFam/XP/gh-pages/output/accounts.json';
const ADDRESS_BOOK_FILE =
'https://raw.githubusercontent.com/MetaFam/TheSource/master/addressbook.json';
const parseAlias = (alias: string) => {
const [type, identifier] = alias.split('/');
return {
type: type.toUpperCase() as Scalars['account_type'],
identifier,
};
};
export const migrateSourceCredAccounts = async (
_: Request,
res: Response,
): Promise<void> => {
const accountsData: SCAccountsData = await (
await fetch(ACCOUNTS_FILE)
).json();
const addressBook: AddressBookEntry[] = await (
await fetch(ADDRESS_BOOK_FILE)
).json();
const accountOnConflict = {
constraint: Account_Constraint.AccountIdentifierTypePlayerKey,
update_columns: [Account_Update_Column.Identifier],
};
const accountList = accountsData.accounts
.filter((a) => a.account.identity.subtype === 'USER')
.map((a) => {
const discordAlias = a.account.identity.aliases.find(
(alias) => alias.description.indexOf(`discord/`) >= 0,
);
const discordId =
discordAlias && discordAlias.description.split('discord/')[1];
const addressEntry =
discordId && addressBook.find((adr) => adr.discordId === discordId);
return {
ethereum_address: addressEntry && addressEntry.address,
scIdentityId: a.account.identity.id,
username: a.account.identity.name,
totalXp: a.totalCred,
Accounts: {
data: a.account.identity.aliases.map((alias) => {
return parseAlias(alias.description);
}),
on_conflict: accountOnConflict,
},
};
});
const result = await client.UpsertPlayer({
objects: accountList,
onConflict: {
constraint: Player_Constraint.PlayerScIdentityIdKey,
update_columns: [
Player_Update_Column.EthereumAddress,
Player_Update_Column.Username,
Player_Update_Column.TotalXp,
],
},
});
res.json(result);
};

View File

@@ -0,0 +1,44 @@
export interface SCAccountsData {
accounts: SCAccount[];
intervalEndpoints: number[];
unclaimedAliases: SCUnclaimedAlias[];
}
export interface SCAccount {
account: SCAccountInfo;
cred: number[];
totalCred: number;
}
export interface SCAccountInfo {
active: boolean;
balance: string;
identity: SCIdentity;
paid: string;
}
export interface SCIdentity {
address: string;
aliases: SCAlias[];
id: string;
name: string;
subtype: string;
}
export interface SCAlias {
address: string;
description: string;
}
export interface SCUnclaimedAlias {
alias: SCAlias;
cred: number[];
totalCred: number;
}
export interface AddressBookEntry {
name: string;
createdAt: number;
address: string;
discordId: string;
}

View File

@@ -1,6 +1,7 @@
import express from 'express';
import { asyncHandlerWrapper } from '../../lib/apiHelpers';
import { migrateSourceCredAccounts } from './migrateSourceCredAccounts/handler';
import { updateBoxProfileHandler } from './updateBoxProfile/handler';
export const actionRoutes = express.Router();
@@ -9,3 +10,8 @@ actionRoutes.post(
'/updateBoxProfile',
asyncHandlerWrapper(updateBoxProfileHandler),
);
actionRoutes.post(
'/migrateSourceCredAccounts',
asyncHandlerWrapper(migrateSourceCredAccounts),
);

View File

@@ -4,7 +4,3 @@ type UpdateBoxProfileResponse = {
success: boolean;
updatedProfiles: Array<string>;
};
type Mutation = {
updateBoxProfile?: Maybe<UpdateBoxProfileResponse>;
};

View File

@@ -28,3 +28,14 @@ export const UpsertAccount = gql`
}
}
`;
export const UpsertPlayer = gql`
mutation UpsertPlayer(
$objects: [Player_insert_input!]!
$onConflict: Player_on_conflict
) {
insert_Player(on_conflict: $onConflict, objects: $objects) {
affected_rows
}
}
`;

View File

@@ -1135,9 +1135,10 @@ type Player {
"""Remote relationship field"""
box_profile: BoxProfile
enneagram: enneagram_type
ethereum_address: String!
ethereum_address: String
id: uuid!
role: String
scIdentityId: String
timezone: Int
totalXp: numeric
username: String!
@@ -1220,6 +1221,7 @@ input Player_bool_exp {
ethereum_address: String_comparison_exp
id: uuid_comparison_exp
role: String_comparison_exp
scIdentityId: String_comparison_exp
timezone: Int_comparison_exp
totalXp: numeric_comparison_exp
username: String_comparison_exp
@@ -1235,6 +1237,9 @@ enum Player_constraint {
"""unique or primary key constraint"""
Player_pkey
"""unique or primary key constraint"""
Player_scIdentityId_key
"""unique or primary key constraint"""
Player_username_unique_key
}
@@ -1257,6 +1262,7 @@ input Player_insert_input {
ethereum_address: String
id: uuid
role: String
scIdentityId: String
timezone: Int
totalXp: numeric
username: String
@@ -1267,6 +1273,7 @@ type Player_max_fields {
ethereum_address: String
id: uuid
role: String
scIdentityId: String
timezone: Int
totalXp: numeric
username: String
@@ -1279,6 +1286,7 @@ input Player_max_order_by {
ethereum_address: order_by
id: order_by
role: order_by
scIdentityId: order_by
timezone: order_by
totalXp: order_by
username: order_by
@@ -1289,6 +1297,7 @@ type Player_min_fields {
ethereum_address: String
id: uuid
role: String
scIdentityId: String
timezone: Int
totalXp: numeric
username: String
@@ -1301,6 +1310,7 @@ input Player_min_order_by {
ethereum_address: order_by
id: order_by
role: order_by
scIdentityId: order_by
timezone: order_by
totalXp: order_by
username: order_by
@@ -1344,6 +1354,7 @@ input Player_order_by {
ethereum_address: order_by
id: order_by
role: order_by
scIdentityId: order_by
timezone: order_by
totalXp: order_by
username: order_by
@@ -1372,6 +1383,9 @@ enum Player_select_column {
"""column name"""
role
"""column name"""
scIdentityId
"""column name"""
timezone
@@ -1390,6 +1404,7 @@ input Player_set_input {
ethereum_address: String
id: uuid
role: String
scIdentityId: String
timezone: Int
totalXp: numeric
username: String
@@ -1649,6 +1664,9 @@ enum Player_update_column {
"""column name"""
role
"""column name"""
scIdentityId
"""column name"""
timezone