@sky-mavis/1more-sdk
v0.0.3
Published
SDK for game partners to integrate with the OneMore platform
Downloads
250
Readme
@sky-mavis/1more-sdk
SDK for game partners to integrate their games with the OneMore platform. This SDK handles the communication between partner games and the main platform using Penpal for secure, promise-based RPC. Works in both iframe (web) and React Native WebView environments.
Installation
npm install @sky-mavis/1more-sdk
# or
yarn add @sky-mavis/1more-sdkQuick Start
import { init, endRound } from '@sky-mavis/1more-sdk';
// Initialize SDK when your game loads
const { parent, destroy } = await init({
// Optional: add extra allowed origins for local development
allowedOrigins: ['http://localhost:3000'],
onRoundStart: (data) => {
// Called when parent starts a new round
console.log('Round started!');
console.log('Token:', data.token);
console.log('Session ID:', data.sessionId);
console.log('Round ID:', data.roundId);
console.log('Target Score:', data.targetScore);
// Store token for API calls
window.arcadeToken = data.token;
sessionStorage.setItem('arcadeToken', data.token);
},
});
// When game round ends, call parent.endRound()
await parent.endRound();
// Or use the standalone function:
await endRound();API
init(config)
Initializes the SDK and establishes a connection with the parent platform.
const { parent, destroy } = await init({
allowedOrigins: ['http://localhost:3000'], // optional
timeout: 10000, // optional, default 10 seconds
onRoundStart: (data) => {
// Handle round start
console.log(data.token, data.sessionId, data.roundId, data.targetScore);
},
});Parameters:
config.allowedOrigins- Additional allowed origins (default origin is always included)config.timeout- Connection timeout in milliseconds (default: 10000)config.onRoundStart- Callback fired when the parent starts a new round
Returns: Promise<IInitResult>
parent- Proxy object to call methods on the parent platformdestroy()- Function to clean up the connection
parent.endRound()
Notifies the parent platform that the game round has ended.
await parent.endRound();endRound() (standalone)
Convenience function that can be called from anywhere after init().
import { endRound } from '@sky-mavis/1more-sdk';
// Anywhere in your game code:
await endRound();Types
Game (Child) Types
interface IInitConfig {
allowedOrigins?: string[];
timeout?: number;
onRoundStart: (data: IRoundStartData) => void;
}
interface IInitResult {
parent: IParentMethods;
destroy: () => void;
}Shared Types
interface IRoundStartData {
token: string;
sessionId: string;
roundId: string;
targetScore: number;
[key: string]: unknown;
}
interface IGameMethods {
startRound: (data: IRoundStartData) => void | Promise<void>;
}
interface IParentMethods {
endRound: () => void | Promise<void>;
}Example: Phaser Integration
import Phaser from 'phaser';
import { init, endRound } from '@sky-mavis/1more-sdk';
declare global {
interface Window {
arcadeToken?: string;
}
}
async function main() {
// Initialize SDK before starting game
await init({
onRoundStart: (data) => {
window.arcadeToken = data.token;
sessionStorage.setItem('arcadeToken', data.token);
console.log('Round started:', data.roundId);
},
});
// Start Phaser game
new Phaser.Game(gameConfig);
}
// Call in your game over scene
export async function notifyGameFinished() {
await endRound();
}
main();Communication Flow
┌─────────────────┐ ┌─────────────────┐
│ OneMore Platform│ │ Partner Game │
│ (Parent) │ │ (Iframe/WebView)│
└────────┬────────┘ └────────┬────────┘
│ │
│ 1. Load iframe or WebView │
│ ─────────────────────────────────────>
│ │
│ 2. Penpal connection established │
│ <═══════════════════════════════════>
│ │
│ 3. parent calls game.startRound() │
│ (token, sessionId, roundId, │
│ targetScore) │
│ ─────────────────────────────────────>
│ │
│ ... game plays ... │
│ │
│ 4. game calls parent.endRound() │
│ <─────────────────────────────────────
│ │Transport Auto-Detection (Game Side)
| Priority | Environment | Detected by | Transport |
|---|---|---|---|
| 1 | Custom | config.messenger provided | User-provided messenger |
| 2 | React Native WebView | window.ReactNativeWebView exists | ReactNativeWebViewChildMessenger |
| 3 | Iframe (default) | Fallback | WindowMessenger via window.parent |
React Native WebView
The SDK works in React Native WebView environments in addition to iframes.
Game side (web page in WebView)
No code changes needed — init() auto-detects window.ReactNativeWebView and uses the appropriate transport.
import { init, endRound } from '@sky-mavis/1more-sdk';
// Works identically in iframe or React Native WebView
const { parent, destroy } = await init({
onRoundStart: (data) => {
console.log('Round started:', data.roundId);
window.arcadeToken = data.token;
},
});
await parent.endRound();Platform side (React Native app)
Use ReactNativeWebViewParentMessenger to bridge the WebView's message channel.
import { useRef, useMemo, useEffect } from 'react';
import WebView from 'react-native-webview';
import {
ReactNativeWebViewParentMessenger,
initParent,
} from '@sky-mavis/1more-sdk';
function GameScreen() {
const webViewRef = useRef<WebView>(null);
const messenger = useMemo(
() =>
new ReactNativeWebViewParentMessenger({
postMessage: (data) => webViewRef.current?.postMessage(data),
}),
[],
);
useEffect(() => {
let destroy: (() => void) | undefined;
initParent({
messenger,
onRoundEnd: () => {
console.log('Game ended the round');
},
}).then((result) => {
destroy = result.destroy;
// Start a round
result.game.startRound({
token: 'abc123',
sessionId: 'session-456',
roundId: 'round-789',
targetScore: 1000,
});
});
return () => destroy?.();
}, [messenger]);
return (
<WebView
ref={webViewRef}
source={{ uri: 'https://game.example.com' }}
onMessage={(e) => messenger.handleMessageFromWebView(e.nativeEvent.data)}
/>
);
}Security
Iframe mode:
- Origin — Only accepts connections from configured
allowedOrigins(Penpal +WindowMessenger) - Source — Only communicates with
window.parent - Default allowed origin:
https://main.new-arcade.axieinfinity.services
React Native WebView mode:
- Native bridge isolation — Communication goes through the native WebView bridge (
window.ReactNativeWebView.postMessage), which is sandboxed to the WebView instance - Protocol validation — Penpal's
validateReceivedMessagefilters out any non-Penpal messages
License
MIT
